配置类也使用继承时的继承
inheritance when config classes also use inheritance
我很难为这个问题设计一个优雅的解决方案。我已将其简化为本质,但这是我正在努力应对的现实情况。
- Base 使用 BaseConfig class 中的一些设置进行初始化并维护这些设置 class。
- Sub 继承自 Base 并扩展其功能。
- Sub 使用并维护 SubConfig 中的一些附加设置。
- SubConfig 继承自 BaseConfig。
问题是 Base 和 Sub 都有自己的 Config classes 副本。当我在 SubConfig 中更改某些内容时,它不会影响 Base 持有的副本,因此不会影响 Base 的行为。
我已经解决了机制问题,但我的解决方案很丑陋。如果您愿意,请向下滚动到示例代码下方以了解详细信息。
#include <cstdio>
struct BaseConfig
{
BaseConfig(int a_) : a(a_) {}
int a;
};
struct Base
{
BaseConfig config;
Base(BaseConfig& c) : config(c) {}
void FuncBase() { printf("a=%d\n",config.a); }
};
struct SubConfig : public BaseConfig
{
SubConfig(int a_, int b_) : BaseConfig(a_), b(b_) {}
int b;
};
struct Sub : public Base
{
SubConfig config;
Sub(SubConfig& c) : Base(c), config(c) {}
void FuncSub() { printf("a=%d\nb=%d\n",config.a, config.b); }
};
int main(int argc, char** argv)
{
SubConfig sc(1,2);
Sub s(sc);
{
printf("Initial state\n");
s.FuncBase();
s.FuncSub();
}
{
printf("Changing a to 3\n");
s.config.a = 3;
s.FuncBase();
s.FuncSub();
}
return 0;
}
现在是我丑陋的解决方案。它在 Base 中同时使用一个对象和一个 BaseConfig 指针。当直接初始化Base时,它使用它的对象变量,并将它的指针设置为对象的地址,所以它使用它自己的BaseConfig副本。当它被 Sub 初始化时,它使用一个指向 Sub 的 SubConfig 的指针。 Base 使用指针版本,因此在这种情况下它将使用 SubConfig 的设置副本。
// config classes are unchanged
struct Base
{
BaseConfig* config;
Base(BaseConfig* c) : config(c), _configObj(*c) {}
Base(const BaseConfig& c) : config(&_configObj), _configObj(c) {}
void FuncBase() { printf("a=%d\n",config->a); }
protected:
BaseConfig _configObj;
};
struct Sub : public Base
{
SubConfig config;
Sub(const SubConfig& c) : Base(&config), config(c) {}
void FuncSub() { printf("a=%d\nb=%d\n",config.a, config.b); }
};
请告诉我有一个明显而优雅的方法来完成这项工作!
如果 Sub 和 Base 共享配置对象,您就不会遇到问题。
实现此目的的一个简单解决方案是使用指针(智能指针)来配置 Base 和 Sub 中的 classes。然后他们可以共享公共配置对象,另外构造函数将是统一的(Base 不会有两个构造函数)。我稍微改变了你的解决方案:
// config classes are unchanged
struct Base
{
BaseConfig* config;
Base(BaseConfig* c) : config(c) {}
void FuncBase() { printf("a=%d\n",config->a); }
~BaseConfig() { delete config; }
};
struct Sub : public Base
{
SubConfig* config;
Sub(SubConfig* c) : Base(config), config(c) {}
void FuncSub() { printf("a=%d\nb=%d\n",config->a, config->b); }
};
但必须明确说明,配置对象的所有者是 Base class,它负责配置释放。
如果你会使用例如c++11 std::shared_ptr class 存储配置然后释放配置对象的问题将消失。
我想到了一种可能的方法,我更喜欢这种方法而不是问题中的丑陋方法。
让函数 类(基础和子)继承它们的配置 类。并使用虚继承保证每个Config变量只有一份。
像这样:
#include <cstdio>
struct BaseConfig
{
BaseConfig(int a_) : a(a_) {}
int a;
};
struct Base : virtual BaseConfig
{
Base(const BaseConfig& c) : BaseConfig(c) {}
void FuncBase() { printf("a=%d\n",this->a); }
};
struct SubConfig : public virtual BaseConfig
{
SubConfig(int a_, int b_) : BaseConfig(a_), b(b_) {}
int b;
};
struct Sub : public Base, public SubConfig
{
Sub(const SubConfig& c) : BaseConfig(c), Base(c), SubConfig(c) {}
void FuncSub() { printf("a=%d\nb=%d\n", this->a, this->b); }
};
int main(int argc, char** argv)
{
SubConfig sc(1,2);
Sub s(sc);
s.FuncBase();
s.FuncSub();
{
printf("Changing a to 3\n");
s.a = 3;
s.FuncBase();
s.FuncSub();
}
{
printf("Changing b to 4\n");
s.b = 4;
s.FuncBase();
s.FuncSub();
}
return 0;
}
我仍在寻找其他能做得更好的答案。
我很难为这个问题设计一个优雅的解决方案。我已将其简化为本质,但这是我正在努力应对的现实情况。
- Base 使用 BaseConfig class 中的一些设置进行初始化并维护这些设置 class。
- Sub 继承自 Base 并扩展其功能。
- Sub 使用并维护 SubConfig 中的一些附加设置。
- SubConfig 继承自 BaseConfig。
问题是 Base 和 Sub 都有自己的 Config classes 副本。当我在 SubConfig 中更改某些内容时,它不会影响 Base 持有的副本,因此不会影响 Base 的行为。
我已经解决了机制问题,但我的解决方案很丑陋。如果您愿意,请向下滚动到示例代码下方以了解详细信息。
#include <cstdio>
struct BaseConfig
{
BaseConfig(int a_) : a(a_) {}
int a;
};
struct Base
{
BaseConfig config;
Base(BaseConfig& c) : config(c) {}
void FuncBase() { printf("a=%d\n",config.a); }
};
struct SubConfig : public BaseConfig
{
SubConfig(int a_, int b_) : BaseConfig(a_), b(b_) {}
int b;
};
struct Sub : public Base
{
SubConfig config;
Sub(SubConfig& c) : Base(c), config(c) {}
void FuncSub() { printf("a=%d\nb=%d\n",config.a, config.b); }
};
int main(int argc, char** argv)
{
SubConfig sc(1,2);
Sub s(sc);
{
printf("Initial state\n");
s.FuncBase();
s.FuncSub();
}
{
printf("Changing a to 3\n");
s.config.a = 3;
s.FuncBase();
s.FuncSub();
}
return 0;
}
现在是我丑陋的解决方案。它在 Base 中同时使用一个对象和一个 BaseConfig 指针。当直接初始化Base时,它使用它的对象变量,并将它的指针设置为对象的地址,所以它使用它自己的BaseConfig副本。当它被 Sub 初始化时,它使用一个指向 Sub 的 SubConfig 的指针。 Base 使用指针版本,因此在这种情况下它将使用 SubConfig 的设置副本。
// config classes are unchanged
struct Base
{
BaseConfig* config;
Base(BaseConfig* c) : config(c), _configObj(*c) {}
Base(const BaseConfig& c) : config(&_configObj), _configObj(c) {}
void FuncBase() { printf("a=%d\n",config->a); }
protected:
BaseConfig _configObj;
};
struct Sub : public Base
{
SubConfig config;
Sub(const SubConfig& c) : Base(&config), config(c) {}
void FuncSub() { printf("a=%d\nb=%d\n",config.a, config.b); }
};
请告诉我有一个明显而优雅的方法来完成这项工作!
如果 Sub 和 Base 共享配置对象,您就不会遇到问题。 实现此目的的一个简单解决方案是使用指针(智能指针)来配置 Base 和 Sub 中的 classes。然后他们可以共享公共配置对象,另外构造函数将是统一的(Base 不会有两个构造函数)。我稍微改变了你的解决方案:
// config classes are unchanged
struct Base
{
BaseConfig* config;
Base(BaseConfig* c) : config(c) {}
void FuncBase() { printf("a=%d\n",config->a); }
~BaseConfig() { delete config; }
};
struct Sub : public Base
{
SubConfig* config;
Sub(SubConfig* c) : Base(config), config(c) {}
void FuncSub() { printf("a=%d\nb=%d\n",config->a, config->b); }
};
但必须明确说明,配置对象的所有者是 Base class,它负责配置释放。 如果你会使用例如c++11 std::shared_ptr class 存储配置然后释放配置对象的问题将消失。
我想到了一种可能的方法,我更喜欢这种方法而不是问题中的丑陋方法。
让函数 类(基础和子)继承它们的配置 类。并使用虚继承保证每个Config变量只有一份。
像这样:
#include <cstdio>
struct BaseConfig
{
BaseConfig(int a_) : a(a_) {}
int a;
};
struct Base : virtual BaseConfig
{
Base(const BaseConfig& c) : BaseConfig(c) {}
void FuncBase() { printf("a=%d\n",this->a); }
};
struct SubConfig : public virtual BaseConfig
{
SubConfig(int a_, int b_) : BaseConfig(a_), b(b_) {}
int b;
};
struct Sub : public Base, public SubConfig
{
Sub(const SubConfig& c) : BaseConfig(c), Base(c), SubConfig(c) {}
void FuncSub() { printf("a=%d\nb=%d\n", this->a, this->b); }
};
int main(int argc, char** argv)
{
SubConfig sc(1,2);
Sub s(sc);
s.FuncBase();
s.FuncSub();
{
printf("Changing a to 3\n");
s.a = 3;
s.FuncBase();
s.FuncSub();
}
{
printf("Changing b to 4\n");
s.b = 4;
s.FuncBase();
s.FuncSub();
}
return 0;
}
我仍在寻找其他能做得更好的答案。