在C ++中使用虚拟类和extern

时间:2010-11-15 22:52:10

标签: c++ class virtual extern

在我还是学生的时候,我一直在用C ++开发一段时间,但我从来没有在任何项目中使用C ++中的虚拟类或extern。我刚刚读到了这两个,并希望有人能更好地理解它们的用法。

虚拟课的目的是什么?可以使用/实现的示例。我在IBM网站上稍微掩饰了一下并写了一个测试程序来看它的实际应用,但什么时候使用虚拟类会很好?

同样适用于extern。我看了一个例子,并在C ++中为自己做了一个测试,但是使用extern而不是使用头文件有什么好处?头文件而不是extern的优点是什么?

3 个答案:

答案 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作为虚拟类来防止这种重复。 感谢