对于罗嗦的标题感到抱歉。这是我正在使用的继承方案的pseduocode,假设C ++和公共继承:
ClassA
ClassB : ClassA
ClassC : ClassA
ClassBB : ClassB
ClassCC : ClassC
我想覆盖ClassA
和ClassBB
ClassCC
中定义的方法。但我只能使用ClassBB
,ClassCC
或新课程。
我知道我可以延长ClassA
,但我需要更改ClassB
和ClassC
的定义(依次为ClassBB
和ClassCC
)看到变化。有了这个限制,我认为我在ClassBB
和ClassCC
都重复了覆盖。还有其他办法吗?
答案 0 :(得分:1)
您可以实现一次全局函数模板,并在ClassBB
和ClassCC
中覆盖函数的定义中调用它。然后,您只需要编写一次实现。这里有一些未经测试的代码:
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); }
};
答案 1 :(得分:0)
如果您不需要访问Base类中的任何受保护成员,只需委托外部函数,可能是上一个答案中建议的模板。
否则,您可以使用多个虚拟继承:
#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实例添加一个模糊的Base类
@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>;
};
答案 2 :(得分:0)
由于您未指定班级A
中的功能是否为虚拟,我们有两种可能性。
如果foo
不是虚拟的,并且您不需要使用BB
指向A
的指针(同样适用于C
和CC
):
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::foo
和B::foo
,但无法从A::foo
访问B
。
如果您需要使用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::foo
与using
私有。在这两种情况下,B
(和C
)都不需要更改,在第一种情况下,A
也是如此。