此笔记为侯捷老师的C++面向对象课程笔记,在开篇中,老师首先讲C++的类,并将类分为两种基本类型:
1、类的成员不带指针的类。
以复数类为例,讲解类的基本知识。
- 类的基本构成:成员变量和成员函数。
构造函数和析构函数的基本语法。
重点是使用初始化列表对类的成员赋初始值的方法。
- public、private、protected三种access的差别,friend右元的作用。
- 重点讲了reference(&)的使用,传值和传引用的区别。
- 在构建类时创建函数的基本思想:函数什么时候作为类的成员函数,什么时候该使用全局函数。
- 内联的作用:类里面定义的函数自动视为内联,类外面的函数尽可能使用内联。
- *** 作符重载。
2、类的成员带指针的类。
以string类为例。
- 主要讲解三大函数:拷贝构造函数、拷贝赋值函数、析构函数。
- 带指针的类必须有拷贝构造函数和拷贝赋值函数。
因为编译器默认的拷贝是逐个bit的拷贝,两个类中都是指针,编译器默认的拷贝执行之后,会变成两个指针指向同一块内存,源指针可能造成内存泄漏。
- complex类中没有指针,不需要析构,离开作用域时类就消失了。
而带指针的函数需要析构。
由于构造函数中有动态分配内存(new),析构函数中配合使用delete。
指针为数组指针时,使用delete[ ];
- 同类的不同对象视为彼此friend,可以访问私有成员变量。
- 赋值动作三步:杀掉自己(delete),分配一块内存给自己(new),拷贝数据(strcpy)。
- 拷贝赋值函数中首先检测自我赋值,为什么内,一是为了提高效率,而是防止可能产生的错误,两个对象本来就指向同一块内存,这时候进行拷贝赋值 *** 作,首先会清掉自己的内存,就直接清掉了两个对象中的数据,无法再执行拷贝 *** 作。
- stack(栈)和heap(堆)。
stack是存在于某作用域(scope)的一块内存空间,调用函数时,函数本身会形成一个stack用来防止所接收的参数以及返回地址。
函数本体内声明的任何变量,所使用的内存块都取自stack。
heap是 *** 作系统提供的一块global内存空间,程序可通过动态分配从其中获得一些内存区块(block)。
- new一个对象的时候,先分配内存(malloc)返回一个void指针,第二步将void指针转换为类的指针,第三步调用构造函数,初始化对象。
- delete一个对象的时候,先调用析构函数,再释放内存(free)。
设计复数类:
#ifndef _COMPLEX_
#define _COMPLEX_
#include
class complex
{
public:
complex(double r = 0, double i = 0)
:re(r), im(i)
{}
complex& operator+= (const complex&);
double real() const { return re; }
double imag() const { return im; }
~complex();
private:
double re, im;
friend complex& _doap1(complex*, const complex&);
};
inline complex&
_doap1(complex* ths, const complex& r)
{
ths->re += r.re;
ths->im += r.im;
return *ths;
}
inline complex&
complex:: operator+= (const complex& r)
{
return _doap1(this, r);
}
complex::~complex()
{
}
/*复数类可能参与复数与实数的运算,所以是全局函数*/
inline complex
operator+ (const complex& x, const complex& y)
{
return complex (x.real() + y.real(),
x.imag() + y.imag()
);
}
inline complex
operator+ (const complex& x, double y)
{
return complex(x.real() + y,
x.imag()
);
}
inline complex
operator+ (double x, const complex& y)
{
return complex(x + y.real(),
y.imag()
);
}
inline std::ostream&
operator<< (std::ostream& os, const complex& x)
{
os << x.real() << "+" << x.imag();
return os;
}
#endif // !_COMPLEX_
测试complex类:
#include
#include "myComplex.h"
int main()
{
complex test1(2, 3);
complex test2(3, 4);
std::cout<< test1+test2 <
设计String类:
#ifndef _MY_STRING_H_
#define _MY_STRING_H_
#include
#include
using namespace std;
class String
{
public:
String(const char* cstr = 0);
String(const String& str);
String& operator = (const String& str);
~String();
char* get_c_str() const { return m_data; }
private:
char* m_data;
protected:
};
inline
String::String(const char* cstr)
{
if (cstr)
{
m_data = new char[strlen(cstr) + 1];
strcpy(m_data, cstr);
}
else
{
m_data = new char[1];
*m_data = '\0';
}
}
inline
String::String(const String& str)
{
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
}
inline String&
String::operator = (const String& str)
{
if (this == &str)
return *this;
delete[] m_data;
m_data = new char[strlen(str.m_data) + 1];
strcpy(m_data, str.m_data);
return *this;
}
inline
String::~String()
{
delete[] m_data;
}
std::ostream& operator << (ostream & os, const String& str)
{
os << str.get_c_str();
return os;
}
#endif // !_MY_STRING_H_
测试String类:
#include
#include "MyString.h"
using namespace std;
int main()
{
String s1;
String s2("hello");
String s3(s2);
s1 = s3;
cout << s1 << endl;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)