删除 C++ 继承中虚拟 class 成员的代码重复
Remove code duplication for virtual class members in C++ inheritance
我现在遇到了一个奇怪的问题。我会写一个真正简化的版本。
class Base
{
public:
virtual int func1()=0;
virtual int func2()=0;
protected:
int n;
};
class der1: public Base
{
// implements the virtual functions of the base and uses the protected data
// members of the base.
};
class der2: public Base
{
// implements the virtual functions of the base and uses the protected data
// members of the base.
}
现在的问题.... der1
和 der2
都以几乎相同的方式实现了 base 的虚函数。但是其他一些 类 (der3
, der4
) 有自己的实现。但是还是需要继承base。
我如何重构代码以 oop 方式删除代码重复?
选项 1
您可以考虑在 Base
class 中使用您最常用的实现。这种方法的主要特点或缺点是基础 class 将不再是抽象的。如果这是一个问题,请转到选项 2。
也许您甚至可以通过使用 template method pattern 来提取由模板方法。
无论如何,对于需要完全不同方法的派生 classes,您只需覆盖 Base class' 方法。
class Base
{
public:
virtual int func1();
virtual int func2()=0;
protected:
virtual void f1_specific_part1()=0;
virtual void f1_specific_part2()=0;
int n;
};
int Base::func1() { // common skeleton of the algorithm
...
f1_specific_part1();
...
f1_specific_part2();
...
}
class Der1: public Base
{
protected:
void f1_specific_part1() override; // Implements the specific variation
virtual void f1_specific_part2() override;
};
选项 2
您可以考虑将派生的 classes 的公共代码分解为 Base
class 的受保护方法。
纯虚函数的重写将只调用基础 class 受保护的公共函数(对于 der1
和 der2
)或者只使用它们自己完全不同的实现(对于 der3
和 der4
)。
class Base
{
public:
virtual int func1()=0;
virtual int func2()=0;
protected:
int common_part1_funct1(); // implements some common parts
int common_part2_funct1();
int n;
};
class Der1: public Base
{
...
int func1() override {
common_part1_funct1();
...
common_part2_funct1();
...
}
};
选项 3 ?
重要说明:我的回答假设大多数派生的 classes 之间有许多共同点。但是,如果您只有一小部分派生的 class 具有一些共同点,那么 Evg 的答案会更合适。
Base12
的想法是:
struct Base {
virtual int func1() = 0;
virtual int func2() = 0;
};
struct Base12 : Base {
protected:
int func12();
};
struct Der1: public Base12 {
virtual int func1() {
return func12();
virtual int func2() {
return func12();
};
struct Der2: public Base12 {
virtual int func1() {
return func12();
virtual int func2() {
return func12();
};
这是一个使用另一个抽象基础的中间层的解决方案class:
class Base12 : public Base {
protected:
int commonFuncStuffA() {
// Commonly used stuff
}
int commonFuncStuffB() {
}
};
class der1: public Base12
{
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = somethingElse;
}
};
class der2: public Base12
{
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = commonFuncStuffB();
}
};
虽然我为真正的生产代码设计所做的看起来有点不同。
为纯虚函数声明一个接口
struct IMyInterface {
virtual int func1() = 0;
virtual int func2() = 0;
virtual ~IMyInterface {}
};
提供一个包含常用数据成员和函数的抽象基础class
class BaseImpl : public IMyInterface {
protected:
int n;
int commonFuncStuffA() {
// Commonly used stuff
}
int commonFuncStuffB() {
// Commonly used stuff
}
};
在最终派生的classes
中提供接口的实现
class der1: public BaseImpl {
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = somethingElse;
}
};
class der2: public BaseImpl {
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = commonFuncStuffB();
}
};
class der3: public IMyInterface {
public:
virtual int func1() {
// Some completely different implementation of the interface
}
virtual int func2() {
// Some completely different implementation of the interface
}
};
class der4: public IMyInterface {
public:
virtual int func1() {
// Some completely different implementation of the interface
}
virtual int func2() {
// Some completely different implementation of the interface
}
};
我现在遇到了一个奇怪的问题。我会写一个真正简化的版本。
class Base
{
public:
virtual int func1()=0;
virtual int func2()=0;
protected:
int n;
};
class der1: public Base
{
// implements the virtual functions of the base and uses the protected data
// members of the base.
};
class der2: public Base
{
// implements the virtual functions of the base and uses the protected data
// members of the base.
}
现在的问题.... der1
和 der2
都以几乎相同的方式实现了 base 的虚函数。但是其他一些 类 (der3
, der4
) 有自己的实现。但是还是需要继承base。
我如何重构代码以 oop 方式删除代码重复?
选项 1
您可以考虑在 Base
class 中使用您最常用的实现。这种方法的主要特点或缺点是基础 class 将不再是抽象的。如果这是一个问题,请转到选项 2。
也许您甚至可以通过使用 template method pattern 来提取由模板方法。
无论如何,对于需要完全不同方法的派生 classes,您只需覆盖 Base class' 方法。
class Base
{
public:
virtual int func1();
virtual int func2()=0;
protected:
virtual void f1_specific_part1()=0;
virtual void f1_specific_part2()=0;
int n;
};
int Base::func1() { // common skeleton of the algorithm
...
f1_specific_part1();
...
f1_specific_part2();
...
}
class Der1: public Base
{
protected:
void f1_specific_part1() override; // Implements the specific variation
virtual void f1_specific_part2() override;
};
选项 2
您可以考虑将派生的 classes 的公共代码分解为 Base
class 的受保护方法。
纯虚函数的重写将只调用基础 class 受保护的公共函数(对于 der1
和 der2
)或者只使用它们自己完全不同的实现(对于 der3
和 der4
)。
class Base
{
public:
virtual int func1()=0;
virtual int func2()=0;
protected:
int common_part1_funct1(); // implements some common parts
int common_part2_funct1();
int n;
};
class Der1: public Base
{
...
int func1() override {
common_part1_funct1();
...
common_part2_funct1();
...
}
};
选项 3 ?
重要说明:我的回答假设大多数派生的 classes 之间有许多共同点。但是,如果您只有一小部分派生的 class 具有一些共同点,那么 Evg 的答案会更合适。
Base12
的想法是:
struct Base {
virtual int func1() = 0;
virtual int func2() = 0;
};
struct Base12 : Base {
protected:
int func12();
};
struct Der1: public Base12 {
virtual int func1() {
return func12();
virtual int func2() {
return func12();
};
struct Der2: public Base12 {
virtual int func1() {
return func12();
virtual int func2() {
return func12();
};
这是一个使用另一个抽象基础的中间层的解决方案class:
class Base12 : public Base {
protected:
int commonFuncStuffA() {
// Commonly used stuff
}
int commonFuncStuffB() {
}
};
class der1: public Base12
{
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = somethingElse;
}
};
class der2: public Base12
{
public:
virtual int func1() {
n = commonFuncStuffA();
}
virtual int func2() {
n = commonFuncStuffB();
}
};
虽然我为真正的生产代码设计所做的看起来有点不同。
为纯虚函数声明一个接口
struct IMyInterface { virtual int func1() = 0; virtual int func2() = 0; virtual ~IMyInterface {} };
提供一个包含常用数据成员和函数的抽象基础class
class BaseImpl : public IMyInterface { protected: int n; int commonFuncStuffA() { // Commonly used stuff } int commonFuncStuffB() { // Commonly used stuff } };
在最终派生的classes
中提供接口的实现class der1: public BaseImpl { public: virtual int func1() { n = commonFuncStuffA(); } virtual int func2() { n = somethingElse; } }; class der2: public BaseImpl { public: virtual int func1() { n = commonFuncStuffA(); } virtual int func2() { n = commonFuncStuffB(); } }; class der3: public IMyInterface { public: virtual int func1() { // Some completely different implementation of the interface } virtual int func2() { // Some completely different implementation of the interface } }; class der4: public IMyInterface { public: virtual int func1() { // Some completely different implementation of the interface } virtual int func2() { // Some completely different implementation of the interface } };