这是使用继承的好方法吗?

时间:2018-02-23 22:17:26

标签: c++ inheritance polymorphism

这是使用继承的好方法吗?

#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)这个程序是否正确,格式正确且没有未定义的行为?

我想创建自己的简单的两级异常层次结构(只有一个基类和一些派生类),我试图在没有任何虚拟方法的情况下找到一种方法。

以下代码确实有效,它似乎以正确的顺序调用析构函数,即使在派生类上没有任何东西可以破坏。然而,我对这项工作的内部结构感到有些困惑。

我知道如果我希望通过其基指针删除派生类,我需要一个虚拟析构函数,但我并没有考虑支持那种多态性。

我知道通过调用message中的B方法,我只是从A调用方法,而后者只返回成员变量{{1} },可以在this_messageA初始化。

将对象传递给catch调用时,B对象是否通过切片过程变为B?但是因为B只是初始化A /的成员与A具有相同的状态,所以最终都会解决。

通过传递包含行号,文件位置等的静态char数组,可以在宏中初始化A类及其派生类。

1 个答案:

答案 0 :(得分:1)

您正在使用标准库std :: cout,所以您肯定应该从std :: exception派生您的异常。

应该正确命名类的名称,例如SomethingException。

使用指针初始化类似乎是错误的,即使它是在.const部分中的某些内容。您已初始化要展开的堆栈中的指针。该指针将在类实例中的副本之前死亡,因为它被抛出。它会起作用,因为地址是.const,但它闻起来会导致未来的维护人员不顾一切。

所以: A - 不是一种好的继承形式。 B - 行为虽然有臭味,但仍定义; - )