http://blog.csdn.net/lushujun2011/article/details/6827555
2011.9.27
1)
定义一个对象时,就调用了构造函数。如果一个类中没有定义任何构造函数,那么C++编译器就会在某种情况下为该类提供一个默认的不带参数的构造函数。
只要一个类中定义了一个构造函数,不管这个构造函数是不是默认的,C++编译器都不会再提供默认的构造函数,所以,如果定义了自己的构造函数还想调用默认的构造函数的话,必须再重新定义一个默认的构造函数。
2)析构函数不允许带参数,并且一个类中只能有一个虚构函数。
3)在类中定义成员变量时,不能直接给成员变量赋初值!!!
4)函数的重载条件:
1、在同一类中 2、同名函数 3、函数参数类型或者参数的个数不同
注意:返回值不同的同名同参函数不能构成重载
特例:函数重载时,要注意函数带有默认参数这种情况
void output(int a , int b = 5);
void output(int a);
调用时,会产生二义性
5)构造函数顺序:父类->子类
析构函数顺序:子类->父类
6)//在main函数里定义一个子类实例时,子类先调用父类带参数的构造函数,
public:
fish():animal(400,300)
{
cout<<"fish construct"<<endl;
}
7)多重继承:
class B : public C ,public D //B多重继承与C与D,用逗号隔开各个基类便可
继承表说明顺序:C在D之前,构造函数调用先,是按基类表的说明顺序进行初始化的。析构函数则相反。
注意多重继承中的函数二义性问题:
例如:C、D类都有同名函数(形参亦同)output(),B多重继承与C、D,则调用a.output时,则编译不过,出现ambiguous多义性问题
8)
animal *pAn; // 父类指针,父类animal有breathe()函数
fish fh; //子类实例,子类重定义了breathe()函数
pAn = &fh; //父类指针指向子类,编译器把子类隐含地转化做父类animal类型,
fn(pAn); // fn是全局函数,这里调用的是父类animal的breathe()函数
上述父类的breathe()若改为虚函数,则调用的是对象的实际类型,也就是pAn是fish的类型,所以最终调用的是子类的breathe()
9)虚函数与多态性
加virtual关键字的函数为虚函数,它体现了C++中的多态性,在编译的时候,利用迟绑定技术,也就是编译时并不确定调用哪个函数,而是在运行时
才依据对象类型来确定调用哪个函数,C++的多态性用一句话概括:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时就会根据对象的实际类型来确定调用相应的函数。
char *p = new char
new指令分配的对象是在堆中分配的,它本质上是执行了一次malloc()调用,并调用了一次构造函数。由new得到的,只是对象的指针,而不是对象本身。更重要的是由new 得到的对象,原则上需要delete。
基本上可以理解为 定义的时候(int a;)分配了内存。但这样说过于简单,并且很不准确。
对于全局变量,变量事实上是预分配的,在程序调入内存,还没执行之前就分配了。
对于静态变量,也是预分配的,但是真正的生效是在第一次执行定义的时候(注意这句话)。
对于自动变量,每次执行定义指令的时候(int a;)都会分配内存。该内存是在栈中分配的。
还有种寄存器变量,基本和自动变量相同。
/*
函数的覆盖:1)在父类和子类中 2)完全相同的函数(形参亦同)3)都是虚函数
函数的隐藏:1.1)在子类和父类中 2)同名函数(形参同) 3)不是虚函数
2.1)在子类和父类中 2)同名函数(形参不同)
简单的区分:同名函数不是函数的覆盖就是函数的隐藏。
函数的覆盖与虚函数多态性联系在一起,与父类子类有关。
函数的多态性是由虚函数体现的。
函数的重载(同名不同参函数)则是在同一个类之中。
有纯虚函数的基类叫做抽象类,它不能定义一个实例,因为它只为派生类服务,
而继承的派生类必须有其函数的具体实现,否则亦是一个抽象类不能定义实例。
#include <iostream> #include <stdio.h> using namespace std; class Base { public: Base(){ cout << "Base()" << endl; } virtual ~Base(){ cout << "~Base()" << endl; } virtual void xfn(int i) {cout<<"Base::xfn(int i):" << i <<endl; } void yfn(float f) {cout<<"Base::yfn(float f):" << f <<endl;} void zfn() {cout<<"Base::zfn()"<<endl;} }; class Derived:public Base { public: Derived(){ cout << "Derived()" << endl; } ~Derived(){ cout << "~Derived()" << endl; } void xfn(int i) {cout<<"Derived::xfn(int i):" << i <<endl; }//覆盖了基类的xfn函数 //void yfn(int c) {cout<<"Derived::yfn(int c):" << c <<endl;} //隐藏了基类的yfn函数 void yfn(float c) {cout<<"Derived::yfn(float c):" << c <<endl;} //隐藏了基类的yfn函数 void zfn() {cout<<"Derived::zfn()"<<endl;} //隐藏了基类的zfn函数 }; int main() { printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); Derived d;//B D printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); Base *pB = &d;// printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); Derived *pD = &d;// printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); pB->xfn();//Dx 5 printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); pD->xfn();//Dx 5 printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); pB->yfn(3.14f); printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); pD->yfn(3.14f); printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); pB->zfn(); printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); pD->zfn(); printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); /*why not the flowlling,do you know? delete pD; printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); delete pB; printf("$$$$$$$$$$$$$$$$%s %d\n", __func__, __LINE__); */ ; }
*/
#include <iostream>
using namespace std;
class Base
{
public:
virtual void xfn(int i) {cout<<"Base::xfn(int i)"<<endl; }
void yfn(float f)
{cout<<"Base::yfn(float f)"<<endl;}
void zfn() {cout<<"Base::zfn()"<<endl;}
};
class Derived:public Base
{
public:
void xfn(int i)
{cout<<"Derived::xfn(int i)"<<endl; }//覆盖了基类的xfn函数
void yfn(int c)
{cout<<"Derived::yfn(int c)"<<endl;} //隐藏了基类的yfn函数
void zfn() {cout<<"Derived::zfn()"<<endl;} //隐藏了基类的zfn函数
};
void main()
{
Derived d;
Base *pB = &d;
Derived *pD = &d;
pB->xfn(5);
pD->xfn(5);
pB->yfn(3.14f);
pD->yfn(3.14f);
pB->zfn();
pD->zfn();
//system("pause");
}