在C++中使用抽象类和内部类是一种好的做法吗
Is it a good practice to use abstract class an inner classes in C++
我有一个类需要维护多个(目前为2或3个)上下文。这些上下文在类之外不可见。目前我的设计如下。在C++中使用抽象类作为内部类是一种好的做法吗?如果你有其他选择,请提出建议。
在下面的例子中:问题是,当编写最初的Car类时,方法(bar1和bar2)是在Sedan的上下文中编写的。现在,我通过引入一种新型汽车(掀背车)来扩展汽车类别。bar1和bar2中的算法是为Sedan类型编写的,不能用于Hatch back类型。不幸的是,我无法更改现有的Car类(即构造函数或方法签名)。因此,我在上面的例子中介绍了Type类。
我的设计方法有意义吗?请提出更好的替代方案或当前设计中的潜在问题。
class Car {
public:
explicit Car(/* sedan-type */) {
// set context as Sedan
}
explicit Car(/* hatchback-type */) {
// set context as Hatchback
}
void bar1() { context_type.bar1() };
void bar2() { context_type.bar2() };
private:
class Type {
virtual void bar1() = 0;
virtual void bar2() = 0;
}
class SedanType {
void bar1() {}
void bar2() {}
}
class HatchBackType {
void bar1() {}
void bar2() {}
}
}
这是一种很好的做法,尤其是如果不同的类具有相似名称的策略,并且您不想混淆它们。如果你不担心这一点,那么有时把它们放在课堂之外就不那么费力了。不过,作为一种Java习语,它相当常见。
通常你只会看到基本的内部类,如果它是抽象的。您绝对不应该为Car
使用不同的构造函数作为参数。你没有把你的担忧分开,也没有让政策变得可替代。
class Base {
public:
Base(SomeAbstractPolicy *policy);
struct SomeAbstractPolicy {
virtual ~SomeAbstractPolicy() {}
virtual void stuff() = 0;
};
};
有时懒惰者会抱怨像这样的控制结构倒置。将具体的策略放在同一个头中或作为类中的静态助手可能是一个合理的折衷方案。
class Base {
public:
Base(SomeAbstractPolicy *policy);
struct SomeAbstractPolicy {
virtual ~SomeAbstractPolicy() {}
virtual void stuff() = 0;
};
static SomeAbstractPolicy *CreateAwesomeConcretePolicy();
static SomeAbstractPolicy *CreateSweetConcretePolicy();
};
您可以更进一步,使用命名构造函数。
class Base {
public:
Base CreateAwesomeBase();
Base CreateSweetBase();
private:
struct SomeAbstractPolicy {
virtual ~SomeAbstractPolicy() {}
virtual void stuff() = 0;
};
Base(SomeAbstractPolicy *policy);
SomeAbstractPolicy *policy;
};
就其价值而言,单元测试要困难得多。
如果你不能有一个基于抽象策略的构造函数,那么抽象属于Car,而不是策略。当你做出这种改变时,这通常是一个更简单的解决方案。代码的味道是,您可以看到方法的整个主体是类型上的一个分支。
为什么不扩展类Car
并重写bar1()
和bar2()
方法。在它们的实现中,你不必调用父类的方法,所以你仍然可以得到你想要的。
例如,让我们以轿车为例:
class SedanCar : public Car {
public :
void bar1() {// do algorithm for sedan};
void bar2() {// do algorithm for sedan};
}
现在,任何调用bar1()
或bar2()
的SedanCar实例都将执行轿车实现。
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 有没有一种方法可以在编译时获得作用域类名
- 对于C++中使用智能指针的指针算术限制,有没有一种变通方法
- 一种在C++中读取TXT配置文件的简单方法
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 在调用接收数组的方法时,模板化数组大小是不是一种糟糕的做法
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 有没有一种"cleaner"的方法可以在指向基的指针向量中找到派生类的第一个实例?
- 有没有一种代码密度较低的方法来使用非默认构造函数初始化数组?
- 将错误返回给调用方而不是立即在 C++ 中抛出错误是否是一种好的做法
- 在 c++ 中,有一种方法可以创建一个包含地图作为值的树状地图?
- 有没有一种优雅而快速的方法来测试整数中的 1 位是否位于连续区域
- 在运行时检查继承是否只有一种类型和 void*
- C++ STD 函数运算符:有没有一种方法可以通过函数将一个向量映射到另一个向量上?
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- 寻找一种更好的方法来表示无符号字符数组
- 我正在寻找一种优雅的方式来从元组向量创建tuple_element向量