20140413 拷贝、赋值构造 变量分配确定时期 子类指针与父类指针转化 虚函数
1、变量内存分配的时间问题
对于全局对象,静态对象以及分配在栈区域内的对象,对它们的内存分配是在编译阶段就完成了;而对于分配在堆区域内的对象,例如,new,它们的分配是在运行是动态进行的。
例子:int i=0;这句话还没有运行时,&i已经有地址了,这就是所谓的编译时就分配好内存
2、c++类创建对象
http://blog.csdn.net/gukesdo/article/details/7514080
分配空间->初始化->赋值
对象的初始化是通过初始化列表来完成。
对象的赋值是通过构造函数的实现体来完成的。
析构函数的作用就是销毁对象中的成员变量,在return 语句时或者作用域结束时使用。
3、拷贝构造函数与赋值构造函数(何时需要拷贝构造函数)
http://blog.sina.com.cn/s/blog_60e96a410100lni7.html(拷贝构造函数和赋值函数--史上最全解释)
在 C++ 中,赋值和拷贝是不同的,
1)拷贝构造函数是对未初始化的内存进行初始化操作
- 比如声明类对象时: 类A,A a=aa;(假设aa是已经初始化的类对象)
- 函数形参为类对象时: 类A,fun(A a),掉用fun时就会进行形参的拷贝(注意:fun(A &a)是不会调用拷贝构造函数的)
2)而赋值是对现有的已经初始化的对象进行操作。(这里我对“已经初始化”的理解是已经调用了构造函数,并且构造函数体可以未执行,只要调用到即可)
- 例如:类A,A a; a=aa;(假设aa是已经初始化的类对象),此时会调用复制构造函数
3)重点:包含动态分配成员的类 应提供拷贝构造函数,并重载"="赋值操作符。(深拷贝)
4)可以说,C++中什么时候有临时对象产生,此时刻c++一定要调用拷贝构造函数。(临时对象产生时有一个特例,此时不需要调用拷贝构造函数,例如类A,A a=1000;)
#include <iostream> using namespace std; class B { public: B() { cout<<"default constructor"<<endl; } ~B() { cout<<"destructed"<<endl; } B(int i):data(i) //B(int) works as a converter ( int -> instance of B) { cout<<"constructed by parameter " << data <<endl; } B & operator=(const B &other) { if(this == &other) return *this; data = other.data; cout<<"constructed by ="<<endl; return *this; } B(const B& other) //拷贝构造函数 { data = other.data; cout<<"constructed by copy"<<endl; } private: int data; }; B Play( B b) { return b ; } int main(int argc, char* argv[]) { B t1 = Play(5); B t2 = Play(t1);//先复制构造将t1复制给Play中的b,然后Play函数返回时,//再复制构造给t2.中间没有出现所谓的临时变量,至少从调试中观察变量data等的地址判断是这样 return 0; }
4、子类和父类指针的转化,虚函数p125
#include<iostream> using namespace std; class A { public: void virtual f() { cout<<"A"<<endl; } }; class B :public A { public: void virtual f() {cout<<"B"<<endl;} }; int main() { A* pa=new A( ); pa->f( ); //输出A B* pb=(B*)pa; //父指针pa强转化为子类指针必须有强制类型 pb->f();//输出A pa=pb;//子指针pb转换为父类指针不需要强制类型 pa->f(); //输出A delete pa,pb; pa=new B(); //pb=(B*)new A();子指针赋给父类pb必须要有强制类型转化 pa->f();//输出B pb=(B*)pa;//父指针pa转化为子类指针必须有强制类型 pb->f();//输出B }
5、形参是类的对象会引用拷贝构造函数,形参是引用不会调用构造函数
#include<iostream> using namespace std; class Animal { public: Animal(){} void eat(){cout<<"eat\n";} Animal(const Animal &a) { cout<<"constructed by copy"<<endl; } }; class Cat: public Animal { public: Cat(){} void Meaw(){cout<<"meaw\n";} Cat(const Animal &a) { cout<<"constructed by copy"<<endl; } }; void Func( Cat an)//对象作为函数参数时调用拷贝构造函数 //void Func(Cat &an)引用做函数参数时只是传递地址,不会调用拷贝构造函数 { an.eat(); } void main() { Cat dao; Func(dao); }