C++类和对象
1.类与对象的定义
1.1 类的定义
1.2 对象的定义
一旦定义了构造函数,默认构造函数将不再存在
class Graph
{...}
int main()
{
Graph g1; //通过默认构造函数或无参构造函数定义对象g1
Graph g2 = Graph(...); //通过构造函数(有参或无参)定义对象g2
}
1.3 何时分配内存
定义类时不分配内存空间,定义该类的对象时才分配内存空间
2.构造函数
1.构造函数和析构不应该定义在private部分
2.如果对象包含成员指针,同时它指向的内存是由new分配,则释放用于保存对象的内存并不会自动释放对象成员指针指向的堆中的内存,因此在类构造函数中使用new来分配内存时,在析构函数中应使用delete来释放分配的内存。
3.对于非static的const数据成员,必须通过构造函数的初始化列表进行初始化,不能在构造函数体内进行赋值。例:
2.1 无参构造函数
最好定义一个无参的、或者定义含参的且参数全部都有默认初始值的构造函数,提供一个代替默认构造函数的构造函数。
2.2 含参构造函数
Graph g2 = Graph(...); //通过含参构造函数定义对象g2
2.3 复制构造函数
(1)复制构造函数的意义、默认复制构造函数:
首先对于普通类型的对象来说,它们之间的复制是很简单的:
int a=100;
int b=a;
对于类而言,系统提供默认的复制构造函数,这种复制是浅复制,其形式可理解为:
class A
{
private:
int data;
public:
A(const A & a)//这个复制构造函数可以不写,系统提供类似的默认复制构造函数!
{
data = a.data;
}
A()
{
data = 3;
}
};
int main()
{
A a;
A a2 = a;
system("pause");
}
(2)拷贝构造函数使用时机:
通过使用另一个同类型的对象来初始化新创建的对象(用于初始化另一个对象)
复制对象把它作为参数传递给函数(对象作为参数)
复制对象,并从函数返回这个对象(对象作为返回值)
(3)深复制与浅复制:
在有指针的情况下,浅拷贝只是增加了一个指针指向已经存在的内存,而深拷贝就是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存,采用深拷贝的情况下,释放内存的时候就不会出现在浅拷贝时重复释放同一内存的错误!
浅复制
class A
{
private:
int size;
char * name;
public:
A(const A & a)//浅复制,未申请新的内存,只是增加了一个指针指向已经存在的内存
{
szie = a.szie;
name = a.name;
}
A(){size = 3;name = NULL;}
}
深复制
class A
{
private:
int size;
char * name;
public:
A(const A & a)//深复制,增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存
{
name = new char[strlen(a.name) + 1];
if(name!=NULL)
{
strcpy_s(name, strlen(a.name) + 1, a.name);
}
size = a.size;
}
A(){size = 3;name = NULL;}
}
3.析构函数
3.1析构函数定义:
析构函数与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数;当程序中没有析构函数时,系统会自动生成以下默认析构函数:
~A(){;}
3.2 注意事项:
(1)对象的构造次序和析构次序是相反的,首先创建的对象最后才被析构;
(2)和其他动态分配的内存一样,如果对象时用new来创建的,那么必须用到delete才能释放,即delete运算时才会调用析构函数。
4.调用子类的构造函数、析构函数
调用派生类的构造函数时,会自动调用基类的构造函数,顺序为:先调用基类构造函数,再执行派生类构造函数本身(即派生类构造函数的函数体);
调用派生类的析构函数时,也会自动调用基类的析构函数,顺序为:先调用派生类的析构函数,再调用基类的析构函数。
5. 静态成员
使用 static 关键字来把数据成员或成员函数定义为静态,静态成员独立于对象存在,可以通过类或对象访问(访问规则仍受public、private等限制?)。
5.1 静态数据成员
静态成员在类的所有对象中是共享的。静态数据成员的初始化应在类的外部进行,如下面的实例所示:
class A
{
private:
int data;
public:
static int objectCount;
A()
{
data = 3;
}
};
// 在类外部初始化类 Box 的静态成员
int Box::objectCount = 0;
访问方法:
a.objectCount 或 A::objectCount
5.1 静态成员函数
(1)如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
(2)静态成员函数与普通成员函数的区别:
- 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
- 普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针。
(3)
6. this指针
this指针用来指向调用成员函数的对象(this作为隐藏参数传递给方法),*this是调用该成员函数的对象本身(的别名)。