这是使用继承的好方法吗?
Is this a good way of using inheritance?
这是使用继承的好方法吗?
#include <iostream>
namespace Test::A {
class A {
char const * const this_message;
public:
constexpr A(char const * const message) noexcept
: this_message(message) {
}
constexpr char const * message() const noexcept {
return this_message;
}
};
struct B : public A {
constexpr B(char const * const message) noexcept
: A(message) {
}
};
}
int main() {
std::cout << sizeof(Test::A::A) << 'n';
std::cout << sizeof(Test::A::B) << 'n';
std::cout << Test::A::B("Test 1").message() << 'n';
try {
char const * const Test4 = "Test 4";
// Uncomment / comment to toggle between
//throw Test::A::B("Test 1");
throw Test::A::B(Test4);
} catch (Test::A::A const a) {
// I'm passing 'a' by copy because the size of 'a'
// will always be either 4 or 8 bytes / it's faster this way.
constexpr auto message = Test::A::B("Test 3").message();
std::cout << a.message() << " " << message << 'n';
}
return 0;
}
我有两个问题:
A) 这是使用继承和...
B) 这个程序是否正确,格式良好,没有未定义的行为?
我想创建我自己的简单两级异常层次结构(只有一个基类和一些派生类),我正在尝试找到一种没有任何虚拟方法的方法。
下面的代码确实有效,它似乎以正确的顺序调用析构函数,即使派生类上没有任何要破坏的内容。然而,我对这个内部是如何工作的有点困惑。
我知道如果我希望通过其基指针删除派生类,我需要一个虚拟析构函数,但我没有考虑支持这种多态性。
我知道通过从B
调用message
方法,我只是从A
调用该方法,而该方法又只返回成员变量this_message
,可以在A
或B
中初始化。
将对象传递给 catch 调用时,B
对象是否通过切片过程变成了A
?但是因为 B 只是初始化了A
/的成员,与A
具有相同的状态,所以最终一切都解决了。
这个想法是通过传递包含行号、文件位置等的静态 char 数组,在宏中初始化A
类及其派生类。
我希望通过其基指针删除派生类,我需要一个虚拟析构函数,但我没有考虑支持这种多态性。
如果你是唯一一个从事项目的程序员,那么这种妥协可能是实用的,但你需要与加入项目的每个人沟通和执行,所以你很难扩展或重用你编写的代码。
将对象传递给 catch 调用时,B 对象是否通过切片过程变成了 A?但是因为 B 只是初始化了 A 的成员/与 A 具有相同的状态,所以最终一切都解决了。
是的,通过切片。 是的,它挂在一起。
这个想法是通过传递包含行号、文件位置等的静态 char 数组,在宏中初始化 A 类及其派生类。
这是另一个问题/陷阱:人们习惯于std::exception
在内部std::string
中捕获文本,因此必须警告其他程序员不要做Test::A::B(my_message_in_a_string.c_str());
和Test::A::B(my_ostringstream.str())
之类的事情,这使得将有用的消息放入异常类变得更加困难。
A) 这是使用继承和...
它授予了按基类型(无论是通过引用还是切片)或派生类型捕获的选项,因此继承增加了有用的功能。
B) 这个程序是否正确,格式良好,没有未定义的行为?
它是,但面对维护,它很脆弱,并且由于缺乏虚拟功能和切片的使用,很难扩展。
您使用的是标准库 std::cout,因此您绝对应该从 std::exception 中派生您的异常。
类的名称应该正确命名,例如 SomethingException。
使用指针初始化类似乎错误,即使它是指向 .const 部分中的内容。您已经初始化了堆栈中要展开的指针。该指针将在类实例中的复制之前死亡,因为它被抛出。它将起作用,因为地址是 .const 但它闻起来,会导致未来的维护者挠头。
所以: A - 不是一种好的继承形式。 B - 行为被定义,尽管很臭;-)
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 打印所有继承的类成员变量和方法
- C++继承 - 为什么调用父方法?
- 继承:调用基类的成员和方法
- 如何继承返回对当前对象的引用的方法?
- C++接口继承不同的参数方法
- 循环依赖,在继承类的情况下使用覆盖方法
- 如何重写继承的嵌套类中存在的虚拟方法
- C++获取所有继承类信息的方法
- CPP 继承虚拟方法解析顺序
- 为什么我可以通过SubBase类的公共继承方法打印出基类的私人继承成员
- 从基类调用继承类的方法.C++
- 工厂方法模式使用继承而抽象工厂模式使用组合如何
- 继承构造函数和其他变量的解决方法
- 解决虚拟方法的歧义继承的两种方法
- C++ 中的类和方法继承
- 与其他模板方法继承 C++ 模板类
- C++类方法继承
- C++对象中的构造函数继承与方法继承
- 类方法继承中的C++类