【问题标题】:Is there a way to make a derived instance use an existing base instance有没有办法让派生实例使用现有的基础实例
【发布时间】:2021-11-16 00:56:21
【问题描述】:

对于像这样的类层次结构:

struct base { int i = 1; };
struct derived final : public base
{
    int j = 2;
    void f() { i = 2; }
}; 
// more derivations from base

我想要一种方法来创建derived 的实例,但使用现有的base 实例。例如:

base b; // b.i == 1
{
derived d;
d.f(); // d.i == 2
}

有没有办法让调用d.f()b.i 的值为2?正如我试图指出的,derived 的生命周期相当短。

从概念上讲,我想让base 看起来像derived 一会儿,“看起来像”意味着访问d.j。完成后,我希望对 d.i 所做的更改“坚持”b.ibase& b 成员变量的明显解决方案不起作用,因为访问 i 需要不同的语法:b.i 而不是 i

完成后将derived 实例复制回base 会起作用;但这似乎很臭。

{
derived d;
d.f(); // d.i == 2
b = d; // copy, YUCK!
}

但我真的只想要并且需要base 的一个实例。


实际发生的事情是我正在尝试simulate nested functions;但我不想更改语法以访问ij

在伪代码中,我想做这样的事情:

struct s final
{
   int i = 1;
   void f()
   {
      int j = 2;
      auto g = [&]();
   }
   // ... other code ...
   void f::g() { i = 10; j = 20; }
};

换句话说,“本地函数”的实际代码远离它的声明位置。

【问题讨论】:

  • “实际情况是我正在尝试模拟嵌套函数;”。 lambda 可能对此有所帮助。
  • 我的意思是您链接中的解决方案(和问题)来自 2002 年。目前,还有其他解决方案。
  • 不清楚您可以在代码中更改什么?正在做b = d;(带切片)解决您的问题吗? ((初始状态和)在d 中所做的更改将被复制到b)。
  • 你如何使用s
  • 你的真实base有多复杂?您能否在 d 中引用共享基础对象中的成员(例如 int &i = b.i;)而不从 base 本身派生?

标签: c++ inheritance allocation local-functions


【解决方案1】:

我看不出有任何方法可以将对象 b 的同一个成员变量与作为 b 的装饰器/视图的 不同 对象 d 共享,因为不同的对象成员变量有不同的值集。

如果derived 派生自base,则base-object 是每个derived-object 的一部分,并且您不能在不破坏固有base-object 的情况下破坏derived-object嗯。

如果derived 不是从base 派生的,则不能在代码中将期望base 对象的变量替换为derived 类型的对象;您的代码中的任何xxx.i 都适用于xxx 作为base 类型的对象或xxx 作为derived 类型的对象,但不适用于两者。因此,将包含xxx.i 的通用代码应用于derived 的对象和base 的对象将不起作用(除非你有像#define impl_f(b) { (b).i = 2; } 这样的宏,但我不认为你认为可重用代码形式为宏)。

我能想到的一种方法是派生类,它强制使用 base-object 进行初始化,并在 derived 被销毁后将(更改的)值复制回此基础对象:

struct base {
    int i = 1;
    base() { }
    base(base &_b) { i = _b.i; }
};

struct derived_base : public base
{
    derived_base(base &_b) : base(_b), b(_b)  {  }
    ~derived_base() { b = *this; }
    
private:

    base &b;
};

struct derived1 final : public derived_base
{
    int j = 2;
    
    derived1(base &_b) : derived_base(_b) { }
    
    void f() { i = 2; }
};



int main() {

base b; // b.i == 1
cout << "b member i (should be 1):" << b.i << std::endl;

{
    derived1 d(b);
    cout << "initially, d member i should be the value of b.i, i.e. 1:" << d.i << std::endl;
    d.f(); // d.i == 2
    cout << "after f(), d member i (should be 2):" << d.i << std::endl;
}

cout << "lifetime of d ended; b has overtaken the values from d" << std::endl;
cout << "b member i (should now be 2, too):" << b.i << std::endl;

}

【讨论】:

    猜你喜欢
    • 2019-08-31
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多