&quot&quot'如果派生类实际上没有继承基类,则必须定义所有虚拟方法。“如何以正确的方式理解这一点?

发布于 2025-02-07 13:34:24 字数 2843 浏览 2 评论 0原文

根据 wiki ,说[强调我的]: 请注意,在配额中的代码片段可以看到在这里

假设在基类中定义了纯虚拟方法。 如果a 得出类,几乎可以继承基类,然后是纯 虚拟方法不需要定义该类别的类 。 但是, 如果派生类不继承基类 实际上,必须定义所有虚拟方法 。下面的代码 可以在这里进行交互探索。

  #include< string>
#include< iostream>

A类{ 
    受保护: 
        std :: string _msg; 
    民众:
        a(std :: string x):_msg(x){} 
        void test(){std :: cout<<“ hello a:”<< _msg<< } 
        虚拟void pure_virtual_test()= 0; }; 

//由于b,c实际上继承了纯虚拟方法> pure_virtual_test不需要定义 
B级:虚拟公共A
{public:b(std :: string x):a(“ b”){}};  
C类:虚拟公共A {
公共:C(std :: String X):A(“ C”){}}; 

//由于b,c实际上继承了一个,每个孩子都必须构建a
//但是,由于D实际上不继承B,C,因此必须定义A *中的纯虚拟方法 * 
D类:公共B,C { 
    民众: 
        d(std :: string x):A(“ d_a”),b(“ d_b”),c(“ d_c”){}
        void pure_virtual_test()覆盖{std :: cout<<“ pure virtual hello hello from:” }}; 

//不必在以后重新定义纯虚拟方法
父母定义了e类:公共D { 
    民众: 
    e(std :: string x):a(“ e_a”),d(“ e_d”){}};


int main(int argc,char ** argv){
    D D(“ D”);
    d.test(); // a:d_a你好
    d.pure_virtual_test(); // pure虚拟hello hello:d_a

    E E(“ E”); 
    e.test(); // a:e_a你好
    e.pure_virtual_test(); //纯虚拟hello hello:e_a 
}
 

如何以正确的方式粗体理解该陈述?

看来,如果派生类(IE 类B)实际上不会继承基类,则可以将 虚拟方法保持不确定 。是我的演示代码片段支持我说的话:

#include <string>
#include <iostream>

class A                     { 
    protected: 
        std::string _msg; 
    public:
        A(std::string x): _msg(x) {} 
        void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; } 
        virtual void pure_virtual_test() = 0;
}; 

// Attention: B does not inherit A ***virtually***, the pure virtual method pure_virtual_test doesn't need to be defined, either.
class B:  public A   { public: B(std::string x):A("b"){}  }; 


class D: public B { 
    public: 
        D(std::string x):B("d_b"){}
        void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; }
}; 

// it is not necessary to redefine the pure virtual method after the parent defines it
class E: public D { 
    public: 
    E(std::string x):D("e_d"){}  
}; 

int main(int argc, char ** argv){
    D d("d"); 
    d.test(); 
    d.pure_virtual_test();

    E e("e"); 
    e.test(); 
    e.pure_virtual_test();
}

As per the wiki, which says that[emphasise mine]:
Note the code snippet in the quotaion is seen here.

Suppose a pure virtual method is defined in the base class. If a
deriving class inherits the base class virtually, then the pure
virtual method does not need to be defined in that deriving class
.
However, if the deriving class does not inherit the base class
virtually, then all virtual methods must be defined
. The code below
may be explored interactively here.

#include <string>
#include <iostream>

class A                     { 
    protected: 
        std::string _msg; 
    public:
        A(std::string x): _msg(x) {} 
        void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; } 
        virtual void pure_virtual_test() = 0; }; 

// since B,C inherit A virtually, the pure virtual method >pure_virtual_test doesn't need to be defined 
class B: virtual public A
{ public: B(std::string x):A("b"){}  };  
class C: virtual public A   {
public: C(std::string x):A("c"){}  }; 

// since B,C inherit A virtually, A must be constructed in each child
// however, since D does not inherit B,C virtually, the pure virtual method in A *must be defined* 
class D: public B,C { 
    public: 
        D(std::string x):A("d_a"),B("d_b"),C("d_c"){}
        void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; } }; 

// it is not necessary to redefine the pure virtual method after the
parent defines it class E: public D { 
    public: 
    E(std::string x):A("e_a"),D("e_d"){}   };


int main(int argc, char ** argv){
    D d("d");
    d.test(); // hello from A: d_a
    d.pure_virtual_test(); // pure virtual hello from: d_a

    E e("e"); 
    e.test(); // hello from A: e_a
    e.pure_virtual_test(); // pure virtual hello from: e_a 
}

How to understand the statement in bold in the right way?

It seems that if the deriving class(i.e. class B) does not inherit the base class virtually, then virtual methods can be left undefined.Here is my demo code snippet to support what I say:

#include <string>
#include <iostream>

class A                     { 
    protected: 
        std::string _msg; 
    public:
        A(std::string x): _msg(x) {} 
        void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; } 
        virtual void pure_virtual_test() = 0;
}; 

// Attention: B does not inherit A ***virtually***, the pure virtual method pure_virtual_test doesn't need to be defined, either.
class B:  public A   { public: B(std::string x):A("b"){}  }; 


class D: public B { 
    public: 
        D(std::string x):B("d_b"){}
        void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; }
}; 

// it is not necessary to redefine the pure virtual method after the parent defines it
class E: public D { 
    public: 
    E(std::string x):D("e_d"){}  
}; 

int main(int argc, char ** argv){
    D d("d"); 
    d.test(); 
    d.pure_virtual_test();

    E e("e"); 
    e.test(); 
    e.pure_virtual_test();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

软的没边 2025-02-14 13:34:24

Wikipedia文章中的描述是错误的/误导性的。

“如果派生类实际上没有继承基类,则必须定义所有虚拟方法”仅当派生类获取 实例化 时才是正确的。单纯的声明,没有实例化,不需要定义纯虚拟方法。

Wikipedia文章的说法是“既然d不会继承b,c实际上,必须定义中的纯虚拟方法”是完全不正确的,并且以下编译没有任何问题,没有任何问题, > d 或e实例化纯虚拟方法:

#include <string>
#include <iostream>

class A                     {
    protected:
        std::string _msg;
    public:
        A(std::string x): _msg(x) {}
        void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; }
        virtual void pure_virtual_test() = 0;
};

// since B,C inherit A virtually, the pure virtual method pure_virtual_test doesn't need to be defined
class B: virtual public A   { public: B(std::string x):A("b"){}  };
class C: virtual public A   { public: C(std::string x):A("c"){}  };

class D: public B,C {
    public:
        D(std::string x):A("d_a"),B("d_b"),C("d_c"){}
};

class E: public D {
    public:
    E(std::string x):A("e_a"),D("e_d"){}
};

int main()
{
    return 0;
}

main是空的,de e 没有问题就声明了。现在,如果您尝试实例化一个或另一个,那么您将遇到问题。

The description in the wikipedia article is wrong/misleading.

"If the deriving class does not inherit the base class virtually, then all virtual methods must be defined" is only true if the deriving class gets instantiated. A mere declaration, without instantiation, does not require definition of pure virtual methods.

The wikipedia article's claim that "since D does not inherit B,C virtually, the pure virtual method in A must be defined" is simply not true, and the following compiles without any issues, without either D or E instantiating the pure virtual method:

#include <string>
#include <iostream>

class A                     {
    protected:
        std::string _msg;
    public:
        A(std::string x): _msg(x) {}
        void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; }
        virtual void pure_virtual_test() = 0;
};

// since B,C inherit A virtually, the pure virtual method pure_virtual_test doesn't need to be defined
class B: virtual public A   { public: B(std::string x):A("b"){}  };
class C: virtual public A   { public: C(std::string x):A("c"){}  };

class D: public B,C {
    public:
        D(std::string x):A("d_a"),B("d_b"),C("d_c"){}
};

class E: public D {
    public:
    E(std::string x):A("e_a"),D("e_d"){}
};

int main()
{
    return 0;
}

main is left empty, and D and E are declared without issues. Now, if you try to instantiate one or the other, then you're going to have problems.

药祭#氼 2025-02-14 13:34:24

引用的文本似乎是指一个称为统治的规则,这导致了一种看起来像虚拟函数的情况,即使是虚拟函数,即使是。这是一个示例:

struct base {
    virtual void f();
};

struct i1 : base {
    // doesn't override base::f
};

struct i2 : base {
    void f() {} // overrides base::f

struct derived : i1, i2 {
};

有了这个层次结构,您可以

derived d;
d.f(); // illegal, because ambiguous:
       // i1::f, inherited from base, or i2::f
i1* p = &d;
p->f(); // calls base::f

很容易地写作,对吗?现在,让我们从base Virtual制作继承。在这里 dominance 启动:

struct base {
    virtual void f();
};

struct i1 : virtual base {
    // doesn't override base::f
};

struct i2 : virtual base {
    void f() {} // overrides base::f

struct derived : i1, i2 {
};

现在只有一个base sub-object,i2 :: f覆盖覆盖base :: f base :: f << /code>,即使在i1中:

derived d;
d.f();    // calls i2::f
i1* i1p = &d;
i1p->f(); // calls i2::f

是的,呼叫i1p-&gt; f()调用i2的版本f,即使i1i2一无所知。仅仅是因为i1i2都是 derived的基础类,并且都具有base> base作为虚拟基础,这起作用。编译器必须为此跨层次结构调用正确的代码。

制作base :: f纯虚拟不会改变有关找到其超级载体的规则。因此,使用非虚拟继承,i1不覆盖base :: f,而derived是一个抽象类。但是,凭借虚拟继承,i2 :: f覆盖base :: f,并且类派生不是抽象的。

The quoted text seems to be referring to a rule called dominance, which leads to a situation where it sort of looks like a virtual function isn't being overridden, even though it is. Here's an example:

struct base {
    virtual void f();
};

struct i1 : base {
    // doesn't override base::f
};

struct i2 : base {
    void f() {} // overrides base::f

struct derived : i1, i2 {
};

With this hierarchy, you can write

derived d;
d.f(); // illegal, because ambiguous:
       // i1::f, inherited from base, or i2::f
i1* p = &d;
p->f(); // calls base::f

Easy enough, right? Now let's make the inheritance from base virtual. Here's where dominance kicks in:

struct base {
    virtual void f();
};

struct i1 : virtual base {
    // doesn't override base::f
};

struct i2 : virtual base {
    void f() {} // overrides base::f

struct derived : i1, i2 {
};

Now there's only one base sub-object, and i2::f overrides base::f, even in i1:

derived d;
d.f();    // calls i2::f
i1* i1p = &d;
i1p->f(); // calls i2::f

Yes, the call i1p->f() calls i2's version of f, even though i1 doesn't know anything about i2. It's only because i1 and i2 are both base classes of derived and both have base as a virtual base that this works. The compiler has to get the code right for this cross-hierarchy call.

Making base::f pure virtual doesn't change the rules about finding its overriders. So with non-virtual inheritance, i1 doesn't override base::f, and derived is an abstract class. But with virtual inheritance, i2::f overrides base::f, and the class derived is not abstract.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文