在C ++中实现虚函数和继承

时间:2012-09-15 11:52:57

标签: c++ inheritance header virtual

所以我有这些头文件:

Shape.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中使用了继承]

关于虚函数..它们的实现与普通函数有什么不同? [我理解行为上的差异]。

2 个答案:

答案 0 :(得分:4)

评论中解释

  

“我得到错误:未定义引用`Shape :: Shape()'”

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

现在,修复了技术问题,请看设计。

前两种方法有两种疾病:(1)虽然它们不应该变异对象,但它们不会被声明const,所以不能在const对象上调用它们,(2) get前缀会降低可读性,更多的是键入并且没有一般优势。我发现一个get前缀在一些罕见的情况下作为消歧设备很有用,但我在初学者看到的所有用法都是不恰当地复制Java约定,这在Java中是有意义的,但在C ++中却没有。所以,而不是......

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

DO

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

然后,方法......

bool isLegal(Shape shape);

在很多方面都是错的......哎哟!但是,让我们从纯粹的技术开始。

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

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 ++构造函数和析构函数的整个机制就在那里,以避免这样的方法和检查。

这个想法就是你......

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

  • 在每种方法中保持对象有效。

然后对象根本无法变为无效。这种方法称为单相构造,使其“有效”的对象属性称为类类不变。哪个应该由每个构造函数建立,并由每个方法维护。

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

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

答案 1 :(得分:1)

第一个版本是正确的:

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

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

Shape::Shape() {..}

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