这几天看C++的一些基础知识发现对虚函数之前理解一直不太清楚,这里记录几点
1) typeid的使用
B * p;//父类
D ob;//B类的子类
p =& ob;//父类指针指向子类对象
当父类中有虚函数功能,子类实现了这个虚函数的时候:
typeid( * p).name() -----得出结果是 class D
typeid(p).name()----得出结论是 classs (B *)
cout << " typeid(p)==typeid(B*) " << endl;
cout << typeid(p->fun()).name();//输出函数返回值类型
------------------------------------------------------------------
class One
{
class Nested {}; //在类中又定义了一个类
Nested* n;
public:
One() : n(new Nested)
{}
~One()
{
delete n;
}
Nested* nested()//类 One的函数
{
return n;
}
};
主应用程序中调用:
One o;
cout << typeid(*o.nested()).name() << endl;//-------会输出:Class One::Nest (注意输出形式)
(如果nest类不是在One中定义,而是在外部进行定义,则这句会输出 Class Nest)
————————————————————————————————————————————————
2)是调用父类函数还是子类函数?
B 父类 有个虚函数fun()
D子类 实现了虚函数fun()
B * p;//父类
D ob;//B类的子类
p =& ob;//父类指针指向子类对象
p->fun();//此时因为父类函数是虚
函数,会调用子类的fun(),而不是父类。(多态就是因此实现的吧?)
B 父类 函数fun()(这里不是虚函数)
D子类 继承函数fun()
B * p;//父类
D ob;//B类的子类
p =& ob;//父类指针指向子类对象
p->fun();//此时因为父类函数不是虚
函数,会调用父类的fun(),而不是子类。
————————————————————————————————————————————————
3)虚函数和析构函数
之前在 effective C++ 编程中就读到过父类的析构函数要是虚函数,一直不太理解
写到程序里运行试了一下:
class CParent
{
public:
CParent()
{
cout<<"parent create ";
}
virtual ~CParent(){ cout<<"Parent Destroy ";}
private:
char *m_pcData;
};
class CChild : public CParent
{
public:
CChild()
{
cout<<"Child create ";
}
~CChild(){cout<<"Child Destroy ";}
private:
char *m_piValue;
};
在主函数中调用:
CParent *pParent;
pParent = new CChild;
delete pParent;//这里这样删除是没有问题的
程序运行依次为:调用CParent,调用CChild,调用~CCChild,调用~CParent。
但是如果在父类的析构函数中没有virtual关键字可就大不一样了
程序依次运行:调用CParent,调用CChild,调用~CCChild。
这里并没有调用~CParent,因为建立的父类对象没有被虚构,这样就造成了内存的泄漏!!
4)虚函数和参数和默认参数
已知类实现如下:
enum ShapeColor{RED, GREEN, BLUE};
一个表示几何形状的类
class Shape {
public:
…
virtual void Draw(ShapeColor color = RED) = 0;
…
};
class Rectangle : public Shape {
public:
…
virtual void Draw(ShapeColor color = GREEN);
…
};
class Circle : public Shape {
public:
…
virtual void Draw(ShapeColor color );
…
};
…..
Shape *pc= new Circle;
Shape *pr = new Rectangle;
pc->Draw(); // pc->Draw() 实现是Circle:draw(RED),
pr->Draw(); //
pr->Draw()实现是Rectangle:draw(RED);
特别注意这里的参数用的可是Shape类的默认参数RED
——————————————————————————————————
class CParent {
public:
......
virtual int WhoLikeThisGame(int x);
private:
char *m_pcData;
};
int CParent::WhoLikeThisGame (int x)
{
......
Cout<<”Parent Like This Game”;
......
}
class CChild : public CParent {
public:
......
virtual int WhoLikeThisGame(char c);
private:
char *m_piValue;
};
......
int CChild:: WhoLikeThisGame (char c)
{
......
Cout<<”Child Likes This Game”;
......
}
……
CParent *pParent;
pParent = new CChild;
pParent-> WhoLikeThisGame(10);//这里输出的是:
Parent Like This Game
因为父类和子类定义的函数参数类型不一样,所以会被认为是重新定义了,并不是被继承了。
因此一定要多注意virtual的用法。