1.构造函数与析构函数
问题:构造函数是什么原理呢?在Test t1(10, 20);中,t1是一个类对象,不是一个函数名, 怎么会和函数调用一样直接双括号加实参呢?他的实现原理是什么呢? 同样Test t1 = Test(10, 20);该构造函数又没有返回值,怎么会作为右值呢?
class Test
{
public:
Test(
int x,
int y)
{
m_x = x;
m_y = y;
}
private:
int m_x;
int m_y;
};
main::
Test t1(
10,
20);
Test t1 = Test(
10,
20);
2.默认构造函数和默认析构函数
如果显示定义一个构造函数和析构函数,那么就会覆盖掉默认的构造函数和析构函数
类中会有一个默认的无参构造函数,一个默认的拷贝构造函数,一个默认的等号操作符
1.当没有任何显示的构造函数(显式的无参构造函数,显式的有参构造函数,显式的拷贝构造函数),默认无参构造函数都会被调用
2.当没有**显示拷贝构造函数**,默认的拷贝构造函数就会调用
3.当没有**显示的析构函数**,默认的析构函数就会被调用
3.拷贝构造函数
编译器会有一个默认的拷贝构造函数 单纯的将另一个对象的成员变量拷贝给自己
void operator=(
const Test& another)
{
m_x = another.m_x;
m_y = another.m_y;
}
Test(
const Test& another)
{
m_x = another.m_x;
m_y = another.m_y;
}
main::
Test t2(
10,
20);
t2.printTest();
Test t3(t2);
t3.printTest();
Test t4 = t2;
t4.printTest();
Test t5;
t5 = t1;
4.构造函数的调用顺序(六种场景)(重点)
void
test1()
{
Test
t1(10, 20);
Test
t2(t1);
}
void func(Test t)
{
cout <<
"func begin..." << endl;
t.printT();
cout <<
"func end..." << endl;
}
void test3()
{
cout <<
"test3 begin..." << endl;
Test t1(
10,
20);
func(t1);
cout <<
"test3 end..." << endl;
}
输出: test3 begin… Test(int x, int y)… Test(const Test &)… //调用fun时,相当于 Test t = t1,调用t的拷贝构造函数 func begin… x = 10, m_y = 20 //调用t.printT(); func end… //cout << “func end…” << endl; ~Test()… //调用t的析构函数 test3 end… //cout << “test3 end…” << endl; ~Test()… //调用t1的析构函数
Test func2(){
cout <<
"func2 begin..." << endl;
Test temp(
10,
20);
temp.printT();
cout <<
"func2 end..." << endl;
return temp;
}
void test4(){
cout <<
"test4 being.. " << endl;
func2();
cout <<
"test4 end" << endl;
}
输出: test4 being.. func2 begin… Test(int x, int y)… x = 10, m_y = 20 func2 end… Test(const Test &)… ~Test()…//先将temp析构 ~Test()…//返回的临时变量因为没有变量承接,func2()调用完毕后编译器就就把这个临时变量析构 test4 end
Test& func2(){
cout <<
"func2 begin..." << endl;
Test temp(
10,
20);
temp.printT();
cout <<
"func2 end..." << endl;
return temp;
}
void test4(){
cout <<
"test4 being.. " << endl;
Test t1 = func2();
t1.printT();
cout <<
"test4 end" << endl;
}
输出: test4 being.. func2 begin… Test(int x, int y)… x = 10, m_y = 20 func2 end… ~Test()… //将temp析构掉 Test(const Test &)… //拷贝构造,Test t1 = func2();会返回一个temp的引用 x = -858993460, m_y = -858993460 test4 end ~Test()…
Test func2(){
cout <<
"func2 begin..." << endl;
Test temp(
10,
20);
temp.printT();
cout <<
"func2 end..." << endl;
return temp;
}
void test5(){
cout <<
"test 5begin.. " << endl;
Test t1 = func2();
cout <<
"test 5 end.." << endl;
}
输出: test 5begin.. func2 begin… Test(int x, int y)… x = 10, m_y = 20 func2 end… Test(const Test &)… ~Test()… test 5 end.. ~Test()…
Test func2(){
cout <<
"func2 begin..." << endl;
Test temp(
10,
20);
temp.printT();
return temp;
}
void test6(){
cout <<
"test6 begin..." << endl;
Test t1;
t1 = func2();
t1.printT();
cout <<
"test6 end.." << endl;
}
输出: test6 begin… Test()… func2 begin… Test(int x, int y)… x = 10, m_y = 20 func2 end… Test(const Test &)… ~Test()… Test(const Test &)… ~Test()… //匿名对象在完成赋值后就会被释放掉 x = 10, m_y = 20 test6 end.. ~Test()…
5.深拷贝和浅拷贝
触发时机:调用了类中默认的拷贝构造函数或者默认的等号操作符
浅拷贝示例
class A
{
private:
int _ma;
int _mb;
char *_mch;
public:
A(
int a,
int b,
char *ch)
{
cout <<
"A(int a, int b, char *ch)" << endl;
_ma = a;
_mb = b;
int len =
strlen(ch);
_mch = (
char *)
malloc(
sizeof(
char)*(len +
1));
strcpy(_mch, ch);
}
~A()
{
cout <<
"~A()" << endl;
if (_mch != NULL)
{
free(_mch);
_mch = NULL;
}
}
};
void fun1()
{
A a1(
10,
20,
"lily");
A a2(a1);
}
A(A &_newa)
{
_ma = _newa._ma;
_mb = _newa._mb;
int len =
strlen(_newa._mch);
_mch = (
char *)
malloc(
sizeof(
char)*(len +
1));
strcpy(_mch, _newa._mch);
}
6.构造函数初始化列表
1).类对象中包含另一个类的对象
2).如果类对象中包含两个或多个类的对象,在构造函数的初始化列表中的成员对象的初始化顺序
class A
{
public:
A(
int a)
{
cout <<
"A()..." << a << endl;
m_a = a;
}
~A()
{
cout <<
"~A()" << endl;
}
void printA()
{
cout <<
"a = " << m_a << endl;
}
private:
int m_a;
};
class B
{
public:
B(A &a1, A &a2,
int b) :m_a1(a1), m_a2(a2)
{
cout <<
"B(A &a1, A &a2, int b)" << endl;
m_b = b;
}
B(
int a1,
int a2,
int b) : m_a1(a1), m_a2(a2)
{
cout <<
"B(int, int, int)..." << endl;
m_b = b;
}
void printB()
{
cout <<
"b = " << m_b << endl;
m_a1.printA();
m_a2.printA();
}
~B()
{
cout <<
"~B().." << endl;
}
private:
int m_b;
A m_a1;
A m_a2;
};
void test1()
{
A a1(
10), a2(
100);
B b(a1, a2,
1000);
b.printB();
}
7.new和delete关键字
new和delete关键字同malloc和free的相同点
new和malloc一样都是在堆中分配一块内存,然后返回该内存在堆中的地址. delete和free一样,都是将堆中的指定内存释放掉
用new开辟的空间可以用free来释放掉 用malloc开辟的空间可以用delete来释放掉
new和delete关键字同malloc和free的不同点
A).malloc和free是标准库stdlib.h中定义的函数,既然是函数,那在调用时就存在入栈出栈操作.而new和delete关键字是C++的操作符,根C中的sizeof一样,不存在函数调用时的入栈出栈操作
B).用6)中的类A来说
A *temp = (A*)malloc(sizeof(A));
//此时malloc不会将成员变量初始化,如果这时候调用temp.printA()输出的则是乱码
A* temp = new A(10);
//new关键字可以在堆中创建一个A空间,同时调用A的构造函数将该空间进行了初始化操作,返回该空间的地址
C).new和delete会触发类的构造函数和析构函数
class Dog
{
public:
Dog(
int id,
char *name)
{
cout <<
"Dog(int id)" << endl;
m_id = id;
int len =
strlen(name);
m_name = (
char *)
malloc(
sizeof(
char)*(len+
1));
strcpy(m_name,name);
}
~Dog()
{
cout <<
"~Dog()" << endl;
if(m_name != NULL)
{
free(m_name);
m_name = NULL;
}
}
void showDog()
{
cout <<
"showDog()" << endl;
}
private:
int m_id;
char *m_name;
};
void fun1()
{
Dog *d1 =
new Dog(
10,
"SUNNY");
d1->showDog();
if (d1 != NULL)
{
delete d1;
}
}
8.static成员变量
初始化方法
static成员变量必须在类的外部进行初始化
类型 类名::静态成员变量 = 值
class Box
{
private:
int len;
int width;
public:
static int high;
Box(
int l,
int w)
{
len = l;
width = w;
}
void volume()
{
cout <<
"high = " << high << endl;
cout <<
"volume = " << len*width*high << endl;
}
};
int Box::high =
10;
在public区
Box b1(10, 20);
b1.volume();
Box::high = 20;//static成员变量放在public区,可以在类外进行修改访问
b1.volume();
在private区
class Box2
{
private:
int len;
int width;
static int high;
public:
Box2(
int l,
int w)
{
len = l;
width = w;
}
void volume()
{
cout <<
"high = " << high << endl;
cout <<
"volume = " << len*width*high << endl;
}
static void setHigh(
int h)
{
high = h;
}
};
Box2 b2(
10,
20);
b2.volume();
Box2::setHigh(
20);
b2.volume();
static 成员类外存储,求类大小,并不包含在内
cout << "sizeof(Goods) = " << sizeof(Goods) << endl;
//8个字节,int len; int width;
//static int high;在data区,不包含在类内
转载请注明原文地址: https://ju.6miu.com/read-34931.html