【问题标题】:Create derived class instance from a base class instance without knowing the class members在不知道类成员的情况下从基类实例创建派生类实例
【发布时间】:2011-01-21 15:24:09
【问题描述】:

这种情况可能吗?

class Base
{
  int someBaseMemer;
};

template<class T>
class Derived : public T
{
  int someNonBaseMemer;

  Derived(T* baseInstance);
};

目标:

Base* pBase = new Base();
pBase->someBaseMemer = 123; // Some value set
Derived<Base>* pDerived = new Derived<Base>(pBase);

pDerived->someBaseMemer 的值应该等于 pBase->someBaseMember 并且与其他基本成员相似。

【问题讨论】:

  • 你为什么要这么扭曲的东西?
  • 堆栈溢出异常?大声笑……严肃地说……这不会编译。
  • @Elite:实际上,如果您将成员更改为公开,它会。但这并没有让它变得不那么可怕。
  • 在我看来,您可以使用它来创建具有您个人想要的功能的对象的合并,同时保留它们自己的功能。想象一下,有一个集合,无论如何,它都能够调用 read() 和 write(),并且正在写入或读取的内容也取决于设备类型(串行端口?文件?内存文件描述符?)。不过,这似乎是一个糟糕的设计。
  • 这似乎是 CRTP 的简单应用,加上从基类实例复制,并将基对象(要复制的)作为引用而不是指针传递给派生 ctor 在C++。 en.wikipedia.org/wiki/Curiously_recurring_template_pattern

标签: c++ visual-c++ inheritance templates


【解决方案1】:

为什么要同时派生和传递基指针?选择其中之一,没有什么能阻止你拥有两者。使用继承为您完成工作:

class Base
{
  public:
    Base(int x) : someBaseMemer(x) {}
  protected:      // at least, otherwise, derived can't access this member
    int someBaseMemer;
};

template<class T>
class Derived : public T
{
  int someNonBaseMemer;

  public:
  Derived(int x, int y) : someNonBaseMemer(y), T(x) {}
};

Derived<Base> d(42, 32); // usage

虽然不是设计的最佳选择。

【讨论】:

  • 令我惊讶的是,人们如此热切地投票回答了这个问题。当 Base 类有更多成员时, Derived(int, int) 构造函数有什么意义?在您的示例类 Derived : public Base 会更好,因为 Derived 类必须识别 Base 类的成员。然而它仍然没有回答我的问题。
  • 不幸的是,您完全没有理解我的意思,即让编译器进行复制。你的例子是一团糟——这对你的观点没有任何帮助。
  • 幸运的是有人能够理解我的混乱并回答我的问题。
【解决方案2】:

someBaseMemr 声明为公开或将声明从class 更改为struct

class Base
{
  public:
  int someBaseMemer;
};

OR

struct Base
{
  int someBaseMemr;
};

请记住,class 默认拥有对所有成员和方法的 private 访问权限。 struct 默认提供public 访问权限。

此外,所有派生类都应从Base 继承public

【讨论】:

  • 发帖者的技术是一种允许更改基类或派生类的派生路径的模式。我也使用过这种技术。
【解决方案3】:

你为什么不真正完成编写和编译代码?

class Base 
{ 
public: // add this
    int someBaseMemer; 
}; 

template<class T> 
class Derived : public T 
{ 
public: // add this
    int someNonBaseMemer; 

    Derived(T* baseInstance)
        : T(*baseInstance) // add this
    { return; } // add this
}; 

这将按照您指定的方式编译和运行。

编辑:或者你的意思是someNonBaseMemer 应该等于someBaseMemer

【讨论】:

  • Derived(T* baseInstance) : T(*baseInstance) 是解决方案。我尝试了 T(baseInstance) 并陷入编译器错误。涉及模板的编译器错误消息,例如。 SomeClass::NestedClass::blablah 让我毛骨悚然。谢谢。
  • 这里有另一个很好的答案,但已被删除。我不知道为什么。 Derived(const T& baseInstance) : T(baseInstance) 也是一个很好的提示,但不适用于我的特殊情况。我的问题中的示例只是一些更大的东西的一小部分。
猜你喜欢
  • 2014-09-29
  • 2011-11-05
  • 1970-01-01
  • 2023-02-22
  • 2020-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多