class A
{
public:
go()
{
cout < < "A " < <endl;
}
};
class B : virtual public A //这里virtual 有用吗 ?偶想问一下大家
{
public:
go()
{
cout < < "B " < <endl;
}
};
class C
{
public:
virtual go()
{
cout < < "A " < <endl;
}
};
class D : public C
{
public:
go()
{
cout < < "D " < <endl;
}
};
int main(int argc, char* argv[])
{
A *x;
B dev;
x=&dev;
x- >go();//结果是 A
C *x1;
D dev1;
x1=&dev1;
x1- >go();//结果是 D
return 0;
}
因为A, B中的go()成员函数不是虚函数啊,B中的go()只是重定义了A中的go()
既然他们不是虚函数,那他们也就没有多态特性,调用的时候就根据指针的类型来调用相应的成员函数。
x是A*指针,所以就调用A::go()
virtual 函数是针对类里面的成员函数,这样该类的继承类能够复写virtual 的成员函数。主要目的:实现多态
virtial 继承,是使用在类之上的,两个类同时virtial 继承一个类,这样被继承的那个类只会产生一个实体,主要目的:避免菱形继承。
虚拟继承原来是防止在多重继承时,可能存在一个共同的基类出现二义性。
如:
A A
¦ ¦
B C
/ /
/ /
/ /
D
这种情况下,一般应该使用虚继承
此时b,c要这样声明:
class b:virtual public a
{};
class c:virtual public b
{};
代价就是不能用基类对象的指针指向虚拟继承类的对象.
********************************************************************
请大家说说内联函数,构造函数,静态成员函数为什么不能为virtual函数?
重点虚函数是运行期间确定的
1 > 内联函数
内联函数是在编译时期展开,而虚函数的特性是运行时才动态联编,所以两者矛盾,不能定义内联函数为虚函数
2 > 构造函数
构造函数用来创建一个新的对象,而虚函数的运行是建立在对象的基础上,在构造函数执行时,对象尚未形成,所以不能将构造函数定义为虚函数
3 > 静态成员函数
静态成员函数属于一个类而非某一对象,没有this指针,它无法进行对象的判别
***********************************************************************************************
昨天在网上看到一篇关于this指针的文章,结果不但没看懂,还暴露出我对虚函数的疑惑.如下:
#include <iostream >
using namespace std;
class CBase
{
public:
virtual void one()
{
cout < < "Base Class/n ";
}
CBase()
{
this - > one();
}
};
class CParent : public CBase
{
public:
CParent()
{
}
virtual void one()
{
cout < < "Parent Class/n ";
}
};
CParent example;
int main()
{
return 0;
}
结果输出是:Base Class
我的疑问是:程序执行CParent example;句时,先调用CBase类的构造函数CBase(),那末它就会执行this- >one()句,而因为CParent类中改写了函数函数one(),那么它必调用的是CParnet的虚函数one()吧?所以输出应该是: Parent Class啊。
/////////////////////////////////////////////////
下面我加一个函数ABC来说明这一点啊。
#include "stdafx.h "
#include <vector >
#include <iostream >
using namespace std;
class CBase
{
public:
virtual void one()
{
cout < < "Base Class/n ";
}
CBase()
{
this- >one();
}
void ABC()
{
cout < < "CBase ABC " < <endl;
this- >one();
}
};
class CParent : public CBase
{
public:
CParent()
{
}
virtual void one()
{
cout < < "Parent Class/n ";
}
};
int main(int argc, char* argv[])
{
// printf( "Hello World!/n ");
// CBase *example;
CParent parent ;
parent.ABC();
return 0;
}
//输出结果:
Base Class
CBase ABC
Parent Class
看,调用ABC时输出的就是Parnet Class,为什么呢?
楼上的说法似乎也有点道理.关于VTABLE什么时候创建的以前我还真没想过.应该是在构造函数调用之后.
还有种解释,因为Parent Clas调用构造函数初始化之前先调用Base Class的构造函数,这时Parent Class的对象并没有生成,所以也不存在VTable之类的东西,当然这时只能调用Base的One函数了.
从对象的角度看:在Base()调用时,基类对象部分构造完成,派生类对象部分尚未构建,此时的对象呈现基类特性。
从虚表的角度看:在Base()调用时,对象的虚表被设为基类的虚表,所以会调用基类的函数;
在CParent()调用后,对象的虚表被reset为派生类的虚表,所以会调用派生类的函数。
XXXXXX基类是看不到父类的成员的
XXXXX通过父类调用才能体现出多态
----------------------------
CBase *example = new CParent;
example- >ABC();
结果是一样的
C++ Primer 3rd Edition 17.5.8节
如果在基类的构造函数中调用了一个虚拟函数,而基类和派生类都定义了该函数的实例,
将会怎么样?应该调用哪一个函数实例?如果可以调用虚拟函数的派生类实例,并且它访问
任意的派生类成员,那么调用的结果在逻辑上是未定义的。而程序可能会崩溃。
为了防止这样的事情发生,在基类构造函数中调用的虚拟实例总是在基类中活动的虚拟
实例。实际上,在基类构造函数中,派生类对象只不过是一个基类类型的对象而已。
对于派生类对象,在基类析构函数中也是如此;派生类部分也是未定义的,但是这一
次不是因为它还没有被构造,而是因为它已经被销毁。
{
public:
go()
{
cout < < "A " < <endl;
}
};
class B : virtual public A //这里virtual 有用吗 ?偶想问一下大家
{
public:
go()
{
cout < < "B " < <endl;
}
};
class C
{
public:
virtual go()
{
cout < < "A " < <endl;
}
};
class D : public C
{
public:
go()
{
cout < < "D " < <endl;
}
};
int main(int argc, char* argv[])
{
A *x;
B dev;
x=&dev;
x- >go();//结果是 A
C *x1;
D dev1;
x1=&dev1;
x1- >go();//结果是 D
return 0;
}
因为A, B中的go()成员函数不是虚函数啊,B中的go()只是重定义了A中的go()
既然他们不是虚函数,那他们也就没有多态特性,调用的时候就根据指针的类型来调用相应的成员函数。
x是A*指针,所以就调用A::go()
virtual 函数是针对类里面的成员函数,这样该类的继承类能够复写virtual 的成员函数。主要目的:实现多态
virtial 继承,是使用在类之上的,两个类同时virtial 继承一个类,这样被继承的那个类只会产生一个实体,主要目的:避免菱形继承。
虚拟继承原来是防止在多重继承时,可能存在一个共同的基类出现二义性。
如:
A A
¦ ¦
B C
/ /
/ /
/ /
D
这种情况下,一般应该使用虚继承
此时b,c要这样声明:
class b:virtual public a
{};
class c:virtual public b
{};
代价就是不能用基类对象的指针指向虚拟继承类的对象.
********************************************************************
请大家说说内联函数,构造函数,静态成员函数为什么不能为virtual函数?
重点虚函数是运行期间确定的
1 > 内联函数
内联函数是在编译时期展开,而虚函数的特性是运行时才动态联编,所以两者矛盾,不能定义内联函数为虚函数
2 > 构造函数
构造函数用来创建一个新的对象,而虚函数的运行是建立在对象的基础上,在构造函数执行时,对象尚未形成,所以不能将构造函数定义为虚函数
3 > 静态成员函数
静态成员函数属于一个类而非某一对象,没有this指针,它无法进行对象的判别
***********************************************************************************************
昨天在网上看到一篇关于this指针的文章,结果不但没看懂,还暴露出我对虚函数的疑惑.如下:
#include <iostream >
using namespace std;
class CBase
{
public:
virtual void one()
{
cout < < "Base Class/n ";
}
CBase()
{
this - > one();
}
};
class CParent : public CBase
{
public:
CParent()
{
}
virtual void one()
{
cout < < "Parent Class/n ";
}
};
CParent example;
int main()
{
return 0;
}
结果输出是:Base Class
我的疑问是:程序执行CParent example;句时,先调用CBase类的构造函数CBase(),那末它就会执行this- >one()句,而因为CParent类中改写了函数函数one(),那么它必调用的是CParnet的虚函数one()吧?所以输出应该是: Parent Class啊。
/////////////////////////////////////////////////
下面我加一个函数ABC来说明这一点啊。
#include "stdafx.h "
#include <vector >
#include <iostream >
using namespace std;
class CBase
{
public:
virtual void one()
{
cout < < "Base Class/n ";
}
CBase()
{
this- >one();
}
void ABC()
{
cout < < "CBase ABC " < <endl;
this- >one();
}
};
class CParent : public CBase
{
public:
CParent()
{
}
virtual void one()
{
cout < < "Parent Class/n ";
}
};
int main(int argc, char* argv[])
{
// printf( "Hello World!/n ");
// CBase *example;
CParent parent ;
parent.ABC();
return 0;
}
//输出结果:
Base Class
CBase ABC
Parent Class
看,调用ABC时输出的就是Parnet Class,为什么呢?
楼上的说法似乎也有点道理.关于VTABLE什么时候创建的以前我还真没想过.应该是在构造函数调用之后.
还有种解释,因为Parent Clas调用构造函数初始化之前先调用Base Class的构造函数,这时Parent Class的对象并没有生成,所以也不存在VTable之类的东西,当然这时只能调用Base的One函数了.
从对象的角度看:在Base()调用时,基类对象部分构造完成,派生类对象部分尚未构建,此时的对象呈现基类特性。
从虚表的角度看:在Base()调用时,对象的虚表被设为基类的虚表,所以会调用基类的函数;
在CParent()调用后,对象的虚表被reset为派生类的虚表,所以会调用派生类的函数。
XXXXXX基类是看不到父类的成员的
XXXXX通过父类调用才能体现出多态
----------------------------
CBase *example = new CParent;
example- >ABC();
结果是一样的
C++ Primer 3rd Edition 17.5.8节
如果在基类的构造函数中调用了一个虚拟函数,而基类和派生类都定义了该函数的实例,
将会怎么样?应该调用哪一个函数实例?如果可以调用虚拟函数的派生类实例,并且它访问
任意的派生类成员,那么调用的结果在逻辑上是未定义的。而程序可能会崩溃。
为了防止这样的事情发生,在基类构造函数中调用的虚拟实例总是在基类中活动的虚拟
实例。实际上,在基类构造函数中,派生类对象只不过是一个基类类型的对象而已。
对于派生类对象,在基类析构函数中也是如此;派生类部分也是未定义的,但是这一
次不是因为它还没有被构造,而是因为它已经被销毁。