【发布时间】:2018-02-23 22:17:26
【问题描述】:
这是使用继承的好方法吗?
#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;
}
我有 2 个问题:
A) 这是使用继承和...的好方法吗?
B) 这个程序是否正确、格式正确且没有未定义的行为?
我想创建自己的简单的两级异常层次结构(只有一个基类和一些派生类),并且我正在尝试找到一种无需任何虚拟方法的方法。
以下代码确实有效,并且它似乎以正确的顺序调用了析构函数,即使派生类上没有什么可破坏的。然而,我对这项工作的内部原理感到有些困惑。
我知道如果我想通过基指针删除派生类,我需要一个虚拟析构函数,但我没有考虑支持这种多态性。
我知道,通过从B 调用message 方法,我只是从A 调用该方法,而它又只返回成员变量this_message,它可以在@987654326 中初始化@ 或B。
将对象传递给catch调用时,B对象是否通过切片过程变成A?但是因为B只是初始化了A的一个成员/和A的状态一样,所以最后都解决了。
这个想法是通过传递包含行号、文件位置等的静态字符数组在宏中初始化 A 类及其派生类。
【问题讨论】:
-
这只是我喜欢保持的一个习惯,我会尽我所能
const。不过,这并不能回答我的问题。 -
尚不清楚为什么
B需要存在。此外,我不确定在函数参数中通过值传递一个小的且可简单复制的类型比通过引用传递快一点的经验法则对于异常处理程序参数也是如此。 -
有了这样一个微不足道的例子,关于它是否是一个“好”的继承例子,没有什么好说的。除此之外,抛出最终源自
std::exception的异常,并始终通过引用捕获它们,否则您可能最终会分割异常并丢弃信息。 -
B需要存在,因为它将代表一种全新的异常类型,具有完全不同的上下文含义。 -
在 C++ 中使用宏是(你在最后一句中说的就是你要去的地方)在 C++ 中通常是非常糟糕的技术。
标签: c++ inheritance polymorphism