首页 > 解决方案 > 有没有办法让派生实例使用现有的基础实例

问题描述

对于类层次结构,例如:

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.i2 之后?正如我试图指出的那样,生命周期derived相当短。

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

将实例复制derivedbase我完成时会起作用;但这似乎很臭。

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

但我真的只想要并且需要一个base.


实际发生的是我正在尝试模拟嵌套函数;但我不想更改语法以访问ij

在伪代码中,我想做类似的事情:

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

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

标签: c++inheritanceallocationlocal-functions

解决方案


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

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

如果derived不是从 派生的base,那么您不能用代码base中的类型对象替换期望 -object 的变量derivedxxx.i你的代码中的any要么xxx作为 type 的对象,base要么作为 typexxx的对象derived,但不能同时适用。因此,将包含xxx.i的对象derived和对象的通用代码应用于base将不起作用(除非您有一个宏#define impl_f(b) { (b).i = 2; },但我不认为您认为 makros 形式的可重用代码)。

我能想到的一种方法是派生类,它强制使用 -object 进行初始化,并在销毁base后将(更改的)值复制回该基对象: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;

}

推荐阅读