有没有办法让派生实例使用现有的基础实例
Posted
技术标签:
【中文标题】有没有办法让派生实例使用现有的基础实例【英文标题】: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.i
。 base& b
成员变量的明显解决方案不起作用,因为访问 i
需要不同的语法:b.i
而不是 i
。
完成后将derived
实例复制回base
会起作用;但这似乎很臭。
derived d;
d.f(); // d.i == 2
b = d; // copy, YUCK!
但我真的只想要并且需要base
的一个实例。
实际发生的事情是我正在尝试simulate nested functions;但我不想更改语法以访问i
或j
。
在伪代码中,我想做这样的事情:
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
本身派生?
【参考方案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;
【讨论】:
以上是关于有没有办法让派生实例使用现有的基础实例的主要内容,如果未能解决你的问题,请参考以下文章
如何让 Widget PendingIntend 重用现有的 MainActivity 实例?