在我还是学生的时候,我一直在用C ++开发一段时间,但我从来没有在任何项目中使用C ++中的虚拟类或extern。我刚刚读到了这两个,并希望有人能更好地理解它们的用法。
虚拟课的目的是什么?可以使用/实现的示例。我在IBM网站上稍微掩饰了一下并写了一个测试程序来看它的实际应用,但什么时候使用虚拟类会很好?
同样适用于extern。我看了一个例子,并在C ++中为自己做了一个测试,但是使用extern而不是使用头文件有什么好处?头文件而不是extern的优点是什么?
答案 0 :(得分:7)
虚拟课程适用于遇到dreaded diamond的情况。例如:
struct Base { int x; };
struct D1 : Base {};
struct D2 : Base {};
struct Derived : D1, D2 {};
此处,Derived
实际上有两个 Base
部分,因此两个成员变量名为x
。它将进行编译,但在通过其基类操作Derived
对象时可能会遇到一些意外行为。
Derived derived;
D1& d1 = derived;
D2& d2 = derived;
d1.x = 1;
d2.x = 2;
cout << d1.x << d2.x << endl; // 12 !
虚拟继承通过Derived
仅从<{1}} 派生来解决此问题。
Base
此处,struct Base { int x; };
struct D1 : virtual Base {};
struct D2 : virtual Base {};
struct Derived : D1, D2 {};
只有一个Derived
部分和一个名为Base
的成员变量。
答案 1 :(得分:3)
没有虚拟类,但有虚拟继承,实际上继承的基类通常称为虚拟基础。
示例:
#include <iostream>
class IHello
{
public:
virtual char const* message() const = 0;
};
class HelloImpl
: public virtual IHello // Use virtual inheritance for interface
{
public:
virtual char const* message() const { return "Hello"; }
};
class Abstract
: public virtual IHello // Use virtual inheritance for interface
{
public:
void sayHello() const
{
using namespace std;
cout << "I'm saying... " << message() << "!" << endl;
}
};
class Concrete
: public Abstract
, public HelloImpl
{};
int main()
{
Concrete().sayHello();
}
这里虚拟继承具有以下效果:
类IHello
只有一个基类子对象。
IHello
的单个子对象由最派生的类直接初始化,此处为Concrete
。
稍微修改了模糊访问的普通规则,以便访问message
即可,而HelloImpl
类通过优势提供message
的实现,有点像Java和C#,除了它在C ++中更通用。
如果用普通继承替换虚拟继承,那么上面的代码甚至都不会编译。
extern
与头文件 extern
和头文件是正交概念。
extern
表示某些内容具有外部链接,extern
是该语言的一部分,即关键字。
头文件是一种打包代码的方式。通常声明放在头文件中,以便可以通过#include
预处理器指令引入这些声明。头文件不是语言的一部分(尽管预处理器是)。
因此,“使用extern
而不是头文件”是没有意义的。
没有特别的关系,没有任何人可以使用一个而不是另一个的任务。
干杯&amp;第h。,
答案 2 :(得分:0)
虚拟类用于消除钻石形状问题。为了更好地理解这个问题,请考虑方案
#include <iostream>
using namespace std;
class A
{
public:
int i;
};
class B:public A
{
public:
int j;
};
class C:public A
{
public:
int k;
};
class D:public B,public C
{
public:
int l;
};
A
/ \
/ \
B C
\ /
\ /
D
这里B和C继承A.所以这两个类中都存在属性(变量和函数)。再次当D继承C和B两者时,B和C的属性以及A类属性存在于D类中复制的类中。因此出现了矛盾。这个问题是钻石形状问题。 这可以删除我将基类A作为虚拟类来防止这种重复。 感谢