仅更改成员的子类是否有效?
Are subclasses that only change the members valid practice?
假设我有一个 class A
,它有一个 int
类型的成员。
我有一个 class B
,它是 A
的子 class。
B
用于将成员初始化为某种状态,没有其他目的。
#include <string>
#include <iostream>
struct A {
int someInt;
A() : someInt(33){}
};
struct B : public A {
B() {
someInt = 4;
}
};
int main() {
A a = A();
A b = B();
std::cout<< a.someInt << std::endl;
std::cout << b.someInt << std::endl;
}
请注意我如何使用 A b = B()
应该发生对象切片的地方。
然而,由于 B
不会向 A
添加任何内容,它是否是使用具有不同构造函数参数的 A
的有效替代方案(或任何其他创建 A
实例的形式) ?
编辑:
背景是我有一个 class 有一些复杂的设置。
将初始化放入单独的子 class 比让我们说写一个构造函数、工厂或构建器要容易得多。
更常见且不易出错的方法是定义静态方法来创建您的 class 实例:
struct A {
static A makeA();
static A makeB();
};
int main()
{
auto a = A::makeA();
auto b = A::makeB();
}
并且为了防止更多错误,您可能希望直接禁止创建 A
的实例,而不是通过将 A
ctor 设为私有来禁止创建静态方法集。
作为更好的做法,
在 class A
中使用另一个构造函数,此构造函数将采用参数 或 在 class A 中使用单独的函数来执行您想要的操作。
并且关于 “将初始化放入单独的子 class 比让我们说写一个构造函数、工厂或构建器要容易得多” 在这方面没有意义情况,所以即使代码像你说的那样复杂也不容易。
为了尽可能直接地回答您的问题,您所做的肯定是“有效的”,因为它将编译 运行 并产生正确的结果。不过,这可能不是最常用的方法。
我建议采用更惯用的方法是使用通用基础 class 并对所有派生版本进行模板化。基本上让编译器完成设置你想要的整数值的工作。
struct ABase {
int someInt;
ABase() = delete;
ABase(int initVal) : someInt(initVal) { }
};
template<int T>
struct A : public ABase {
A() : ABase(T) {}
};
int main() {
ABase a = A<33>();
ABase b = A<4>();
std::cout << a.someInt << std::endl;
std::cout << b.someInt << std::endl;
}
这可能是总体上更少的代码(特别是如果你有不止两个版本的这个class),而且更灵活。
假设我有一个 class A
,它有一个 int
类型的成员。
我有一个 class B
,它是 A
的子 class。
B
用于将成员初始化为某种状态,没有其他目的。
#include <string>
#include <iostream>
struct A {
int someInt;
A() : someInt(33){}
};
struct B : public A {
B() {
someInt = 4;
}
};
int main() {
A a = A();
A b = B();
std::cout<< a.someInt << std::endl;
std::cout << b.someInt << std::endl;
}
请注意我如何使用 A b = B()
应该发生对象切片的地方。
然而,由于 B
不会向 A
添加任何内容,它是否是使用具有不同构造函数参数的 A
的有效替代方案(或任何其他创建 A
实例的形式) ?
编辑: 背景是我有一个 class 有一些复杂的设置。 将初始化放入单独的子 class 比让我们说写一个构造函数、工厂或构建器要容易得多。
更常见且不易出错的方法是定义静态方法来创建您的 class 实例:
struct A {
static A makeA();
static A makeB();
};
int main()
{
auto a = A::makeA();
auto b = A::makeB();
}
并且为了防止更多错误,您可能希望直接禁止创建 A
的实例,而不是通过将 A
ctor 设为私有来禁止创建静态方法集。
作为更好的做法,
在 class A
中使用另一个构造函数,此构造函数将采用参数 或 在 class A 中使用单独的函数来执行您想要的操作。
并且关于 “将初始化放入单独的子 class 比让我们说写一个构造函数、工厂或构建器要容易得多” 在这方面没有意义情况,所以即使代码像你说的那样复杂也不容易。
为了尽可能直接地回答您的问题,您所做的肯定是“有效的”,因为它将编译 运行 并产生正确的结果。不过,这可能不是最常用的方法。
我建议采用更惯用的方法是使用通用基础 class 并对所有派生版本进行模板化。基本上让编译器完成设置你想要的整数值的工作。
struct ABase {
int someInt;
ABase() = delete;
ABase(int initVal) : someInt(initVal) { }
};
template<int T>
struct A : public ABase {
A() : ABase(T) {}
};
int main() {
ABase a = A<33>();
ABase b = A<4>();
std::cout << a.someInt << std::endl;
std::cout << b.someInt << std::endl;
}
这可能是总体上更少的代码(特别是如果你有不止两个版本的这个class),而且更灵活。