gpt4 book ai didi

简单场景的 C++ OO 继承正确性

转载 作者:搜寻专家 更新时间:2023-10-31 00:33:20 28 4
gpt4 key购买 nike

我正在尝试使用以下简单模型在 C++ 中创建继承层次结构:类(class)、模块和类(class),其中类(class)由零个或多个模块组成,模块由零个或多个类(class)组成。这些类中的每一个还包含其他信息:

class course
{
private:
const std:string & name_;
const std::duration duration_;
const difficulty difficulty_;
...
};

class module
{
private:
const std:string & name;
const std::duration duration;
...
};

class lesson
{
private:
const std:string & name;
const std::duration duration;
...
};

我的问题:

  • 拥有一个所有这三个都继承的类是否正确,该类包含它们的共同属性?

就我个人而言,我认为他们以下列方式从 Vector 继承更正确:

class course : public std::vector<module>
{
private:
const std:string & name_;
const std::duration duration_;
const difficulty difficulty_;
...
};

class module : public std::vector<lesson>
{
private:
const std:string & name;
const std::duration duration;
...
};

class lesson
{
private:
const std:string & name;
const std::duration duration;
...
};

由于类(class)是模块的集合,而模块是具有一些附加属性的类(class)的集合,从 vector 继承将提供添加、删除等模块和类(class)所需的所有标准功能。

  • 为什么不两者兼而有之?我在学校学习继承的方式是使用 Java,我被告知多重继承是邪恶的,并且为了使用 Liskov Substitution Principle 进行适当的 OO 继承而远离它。等等。有很多人不相信它,也有很多人发誓。

另一种可能的方式是:

class course : public namedentity
{
private:
std::vector<module> modules_;
...
const difficulty difficulty_;
...
};

class module : public namedentity
{
private:
std::vector<lesson> lesons_;
...
};

class lesson : public namedentity
{
private:
...
};

其中 namedentity 包含所有公共(public)属性,而这些私有(private) vector 包含它们的子 vector 。

我想归根结底是,类(class)真的是vector<module> , 和模块真的 vector<lesson> ?这是否违反了 LSP 或其他 OO 原则?将他们的 child 作为属性(property)会更好吗?

最佳答案

不建议从 vector 公开继承,因为类(class)、类(class)或模块不是 vector 。

刚好你用vector来实现,因为一个模块可以有好几门类(class)。如果明天您要使用集合、映射、链表或数据库映射器来实现您的对象,那么如果您基于 vector 继承,则必须重写整个代码。不要忘记,标准 vector emplace()、push_back()、erase() 等需要重载,因为模块中类(class)的所有这些操作都需要调整类(class)持续时间。

顺便说一句,类设计的一个好的经验法则是对“is-a” 关系使用继承,对“has-a” 使用组合。

支持和反对 vector 继承的更多论点是 in this SO question .

第二种选择看起来更好,因为一门类(class)、一节课、一个模块实际上是一个命名实体。使用这种方法,对象之间的关系也更加清晰

这两种方法都符合 Liskov 替换原则:

  • 如果您为 namedentity 编写代码,可以使用相同的代码用这些子类中的任何一个替换命名实体(前提是它们都实现了可以使用与基类相同的参数的构造函数)。无论您将来对数据结构进行何种改进,这都是有意义的。
  • 如果您编写代码来处理 vector<module> ,相同的代码可以与 course 一起使用反而。但是,您有可能在构造函数中使用不同的语义。如果你改变你的实现,LSP 会适得其反。

关于简单场景的 C++ OO 继承正确性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28999687/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com