用C++实现了虚拟函数和继承

implementing virtual function and inheritance in C++

本文关键字:函数 继承 虚拟 C++ 实现      更新时间:2023-10-16

所以我有这些头文件:

形状.h:

class Shape
{
public:
Shape();
virtual ~Shape();
virtual double getArea();
virtual void printDraw();
bool isLegal(Shape shape);
};

Trig.h:

class Trig : public Shape
{
public:
Trig(Point pointA, Point pointB, Point pointC);
virtual ~Trig();
virtual double getArea();//override
virtual void printDraw();//override
bool isLegal(Trig trig);//override
};

但是当我尝试实现Trig.cpp时,我会遇到错误。我试过了:

Trig::Trig(Point pointA, Point pointB, Point pointC) {..}

我浏览了一下互联网,但我似乎没有正确地继承遗产。[我的代码必须有只包括声明的头文件!…赋值的要求!]

我在C++中同时使用继承和虚拟函数是新手[我在Java中使用过继承]

关于虚拟函数。。它们的实现与正常功能相比有什么不同吗?[我理解行为上的差异]。

评论中,您解释了

“我得到错误:对"Shape::Shape()"的未定义引用;

这意味着您忘记提供该构造函数的实现。

现在,随着技术问题的解决,看看设计。

前两种方法有两个缺点:(1)尽管它们永远不应该突变对象,但它们没有被声明为const,因此不能在const对象上调用;(2)get前缀降低了可读性,更易于键入,没有一般优势。我;我发现get前缀在一些罕见的情况下作为消歧设备很有用,但所有的用法我都很喜欢;初学者看到的是对Java约定的不适当复制,这在Java中是有意义的,但在C++中却没有。因此,不要使用…

virtual double getArea();
virtual void printDraw();

进行

virtual double area() const;
virtual void print() const;

然后,方法…

bool isLegal(Shape shape);

在很多方面都是错误的…哎哟但让我们;让我们从纯粹的技术开始。

从纯粹的技术角度来看,按值传递参数的效率是不必要的,这会导致每次调用都有一个复制操作。而是通过引用传递对象。并将其作为对const的引用,以便支持const对象和右值对象作为自变量:

bool isLegal(Shape const& shape);

接下来,命名:isLegal是一个不好的名称,因为大多数C++对象都是合法的。比如说,它必须是色情的,并且居住在非西方国家,才能成为非法的。我可以;就我的一生而言,我想不出任何方法来让一个物体变得色情,或者让它位于某个特定的地理区域。

所以,

bool isValid(Shape const& shape);

接下来,在低级别设计中,没有充分的理由将非virtual方法作为普通成员函数,因为这需要在对象上调用它。但它所需要的所有信息都在普通的争论中。我们可以在派生类中看到这种混淆,其中…

bool isLegal(Trig trig);//override

根本不是重写:从技术上讲,它是函数名的重载,这意味着,只是一个同名的不同函数。有;这里没有虚拟,没有覆盖。这是不需要的。

所以,让它成为static成员函数,它不必在对象上调用:

static bool isValid(Shape const& shape);

最后,在更高层次的设计中,C++构造函数和析构函数的整个机制都在那里,以避免这种方法和检查。

这个想法是你…

  • 在每个构造函数中建立一个有效的对象。

  • 在每个方法中保持对象的有效性。

然后对象可以简单地;t无效。这种方法被称为单相构造,并且使其“有效的;被称为班级类不变量。它应该由每个构造函数建立,并由每个方法维护。

这意味着,在最终版本中,isValid函数被删除:它没有工作要做,因为该工作是由构造函数和方法(正确地)完成的。

好吧,单阶段构造有一些技术挑战,特别是如何在基类构造函数中进行派生类特定的初始化。这包含在C++常见问题解答中。它;阅读常见问题解答通常是个好主意。

第一个版本是正确的:

Trig::Trig(Point pointA, Point pointB, Point pointC) {..}

它将编译,但不会链接。原因是已声明Shape的无参数构造函数,但未能定义。她添加了一个定义

Shape::Shape() {..}

或者,如果默认构造函数为OK,则从Shape的标头中删除声明。