如果一个基类有2个派生类,并且这些类每个都有一个派生类.那么我可以为大多数派生类扩展一个基方法*一次*吗

If a base class has 2 derived classes, and those classes each have a derived class, can I extend a base method *once* for the most derived classes?

本文关键字:派生 一个 大多数 我可以 扩展 方法 一次 2个 基类 如果 有一个      更新时间:2023-10-16

很抱歉标题太冗长。以下是我正在使用的继承方案的pseduo代码,假设C++和公共继承:

ClassA
ClassB : ClassA
ClassC : ClassA
ClassBB : ClassB
ClassCC : ClassC

我想覆盖ClassA中为ClassBBClassCC定义的方法。但我只能使用ClassBBClassCC或一个新类。

我知道我可以扩展ClassA,但我需要更改它们的ClassBClassC的定义(进而更改ClassBBClassCC)才能看到更改。有了这个限制,我想我不得不在ClassBBClassCC中复制覆盖。有别的办法吗?

您可以实现一次全局函数模板,并在ClassBBClassCC中的重写函数的定义中调用它。那么,你只需要写一次隐含语。下面是一些未经测试的代码:

struct A
{
     virtual void foo() {}
};
struct B : public A {};
struct C : public A {};
template<typename T>
void foo_impl(T const& t)
{
     //do something with t
};    
struct BB : public B
{
     virtual void foo() { foo_impl(*this); }
};
struct CC : public C
{
     virtual void foo() { foo_impl(*this); }
};

由于您尚未指定类A中的函数是否为虚拟函数,因此我们有两种可能性。

如果foo不是虚拟的,并且不需要将BB与指向A的指针一起使用(CCC也是如此):

class A { public: void foo(); }
class B : public A {} // `A::foo` can be accessed from B.
class BB : public B
{
public:
  // Problem (1): `A::foo` can be accesed from B, and `BB::foo` is another function.
  void foo() { <other_behaviour> } 
};

为了避免问题(1),您可以将A::foo设为私有:

class A { public: void foo(); }
class B : public A {} // `A::foo` can be accesed from B.
class BB : public B
{
public:
  void foo() { <other_behaviour> } 
private:
   using A::foo; // `A::foo` can't be accessed from B.
};

在这种情况下,您现在有两个函数:A::fooB::foo,但不能从B访问A::foo

如果您需要将BB::foo()与指向A(或B)的指针一起使用,或者A::foo已经是虚拟的:

class A { public: virtual void foo(); }
class B : public A {} // `A::foo` can be accessed from B.
class BB : public B
{
public:
  // Problem (2): `A::foo` and `B::foo` are two different functions, but for using `A::foo`,
  // the user must write `A::foo()` to call it, and don't simply `foo()`.
  void foo() { <other_behaviour> } 
};

要解决(2),可以执行相同的操作,将A::foousing私有化。在这两种情况下,B(和C)都不需要更改,在第一种情况下也不需要更改A

如果您不需要访问基类中的任何受保护成员,只需委托给一个外部函数,可能是上一个答案中建议的模板。

否则,您可以使用多个虚拟继承:

#include <iostream>
class Base
{
public:
    virtual void foo() {std::cerr << "Base::foo: " << (++i) << std::endl;};
    Base() : i(0) {}
    virtual ~Base() {}
protected:
    int i; // the state that you need to access in foo()
};
class Implement: public virtual Base
{
public:
     void foo() override {std::cerr << "Implement::foo: " << (++i) << std::endl;}
};
class D1: public Base{};
class D2: public Base{};
class DD1: public D1, public Implement
{
public:
    virtual void foo() override {Implement::foo();}
};
class DD2: public D2, public Implement
{
public:
    virtual void foo() override {Implement::foo();}
};
int main()
{
    DD1 dd1;
    dd1.foo();
    D1 &d1r = dd1;
    d1r.foo();
    D1 d1;
    d1.foo();
}

一个限制是,您的DD1和DD2实例最终会有一个不明确的基类

广告由@Ben Voigt建议,CRPT是一个很好的替代方案,可以在不受模糊基类限制的情况下解决相同的问题:

template <class D>
class CRTP
{
protected:
    void foo_impl(D &d) {std::cerr << "CRTP::foo_impl: " << (++d.i) << std::endl;}
};
class DD2: public D2, public CRTP<DD2>
{
public:
    virtual void foo() override {CRTP<DD2>::foo_impl(*this);}
    friend class CRTP<DD2>;
};
相关文章: