【问题标题】:Redefinition of C++ classes重新定义 C++ 类
【发布时间】:2014-02-02 20:14:58
【问题描述】:

我有这个无法更改的代码:

啊.h

 class B;
 class A
{
  A();
  void * getB();
  private:
  B * b;
}

A.cxx

namespace
{
    class B : public QTabWidget
    {
        foo()
        {
         ...
        }
        bar()
        {
         ...
        }
    }
}
A::A()
{
    b = new B();
}
A::getB()
{
    return b;
}

我想在继承 A 的类中访问 b 及其方法(foo 或 bar 或继承的方法)。 我可以这样做吗?

C.h

class C : public A
{
  C();
  private:
  D * d;
}

C.cxx

namespace
{
    class D : public QTabWidget //Exact copy of class B
    {
        foo()
        {
        ... 
        }
        bar()
        {
        ...
        }
    }
}
C::C()
{
    d = (D*) getB();
    d.foo()
    d.bar()
}

安全吗?是否允许?我已经尝试过了,它似乎有效。 如果它是安全的,我可以用更多的静态方法,或方法,甚至属性来扩展 D 吗?

【问题讨论】:

  • 从编译器的角度来看,这将起作用,因为它是D 类型的简单副本。但是,从设计的角度来看,我不知道是否允许。

标签: c++ inheritance redefinition


【解决方案1】:

不,这不安全。

理论上,只要D 的第一部分与B 相同,您就可以使其工作。您也可以将新内容附加到 D

但实际上,这通常是一个非常糟糕的主意。您依靠手动保持类彼此同步。更重要的是,您依赖编译器以完全相同的方式处理这两个类,这可能取决于各种配置选项(例如打包)。

如果您犯了最轻微的错误,那么您将得到未定义的行为,因为程序最终可能会访问或执行任意内容。至关重要的是,它可能似乎工作了一段时间,然后突然以多种方式意外中断。这类问题很难追踪,因为您故意绕过编译器的类型检查。

【讨论】:

  • 那我该怎么办?我需要访问这个类。我也可以在 C.cxx 中包含 A.cxx,但我收到一个警告:警告:'..' 有一个字段'...',其类型使用匿名命名空间。这是一个更好的主意吗?
  • 我同意“同步类”部分。但是考虑到这个重复的类中根本没有属性,它真的可以随时中断吗?如果我调用 d.foo(),会执行哪些二进制代码? B ou D 生产的那一款?
  • 如果类B 没有属性,那么为什么函数需要是成员方法?您可以将它们声明为全局函数并直接调用它们,忽略对象。
  • 我无法修改 B 类中的任何内容。实际上 B 没有自己的属性,但是它具有继承的属性,我需要访问。
  • 在这种情况下,您能做的最好的事情就是reinterpret_cast 指向基类类型的指针。这并不理想,您将无法访问其任何受保护的成员。但是,由于您将指针强制转换为在其继承层次结构中合法的类型,因此它应该是安全的。 (为了更加安全,您通常希望在这种情况下使用 dynamic_cast。但是,这是不可能的,因为 B 声明是隐藏的。)
猜你喜欢
  • 2019-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多