C ++虚拟方法只覆盖一个

时间:2015-12-17 10:25:56

标签: c++ inheritance

这是父类Foo,它是抽象的(虚拟的)。 并且Foo类'方法在Foo.cpp中声明。

[foo.h中]

class Foo
{
public:
    Foo();
    ~Foo();
    virtual void methodA(int no, const char* path) = 0;
    virtual void methodB(const char* name, const char* path) = 0;
    virtual void methodC(const char* name, const char* path) = 0;
    // ... more 20 virtual methods 
}

[Foo.cpp中]

Foo::Foo(){}
Foo::~Foo(){}
Foo::methodA(int no, const char* path)
{
    // do something
}
Foo::methodB(const char* name, const char* path)
{
    // do something
}
Foo::methodC(const char* name, const char* path)
{
    // do something
}
// ... more 20 methods

Foo班级中,必须使用参数methodA调用no。 此外,参数no必须从0开始依次增加。

非常不舒服。所以我想覆盖子类methodA中的Bar

Bar类有一个memeber变量m_nomethodA没有参数no。 调用m_no时,methodA会增加。

这是我的代码。

[Bar.h]

class Bar : public Foo
{
public:
    Bar();
    ~Bar();
    void methodA(const char* path);
private:
    int m_no;
}

[Bar.cpp]

Bar::Bar() : m_no(0) {}
Bar::~Bar() {};
Bar::methodA(const char* path)
{
    Foo::methodA(m_no++, path);
}

但是类Bar是抽象的(虚拟),因为类Bar不是声明虚拟方法(methodAmethodBmethodC和20种方法更多)。

所以,我编辑了。

[Bar.h]

class Bar : public Foo
{
public:
    Bar();
    ~Bar();
    void methodA(const char* path);
    void methodB(const char* name, const char* path);
    void methodC(const char* name, const char* path);
    // ... more 20 methods
private:
    int m_no;
}

[Bar.cpp]

Bar::Bar() : m_no(0) {}
Bar::~Bar() {};
Bar::methodA(const char* path)
{
    methodA(m_no++, path);
}

Bar::methodA(int no, const char* path)
{
    Foo::methodA(no, path);
}

Bar::methodB(const char* name, const char* path)
{
    Foo::methodB(name, path);
}

Bar::methodC(const char* name, const char* path)
{
    Foo::methodC(name, path);
}

// ... more 20 methods

如何在不声明所有虚拟方法的情况下继承类Foo

3 个答案:

答案 0 :(得分:2)

  

如何在不声明所有虚拟方法的情况下继承Foo类?

您为他们提供了实施。

(注意:这部分增加了@TommyA的答案,但评论时间太长;请参阅第二部分,了解不同的方法)

考虑:

class Foo
{
public:
    Foo();
    virtual ~Foo() = 0; // this is the only pure virtual function
    virtual void methodA(int no, const char* path);
    virtual void methodB(const char* name, const char* path);
    virtual void methodC(const char* name, const char* path);
    // ... more 20 virtual methods 
}

Foo.cpp中:

Foo::~Foo() = default; // unless you need to add some impleemntation

// other methods implemented like you did

栏:

class Bar : public Foo
{
public:
    Bar();
    virtual ~Bar();
    void methodA(const char* path);
    // do not implement anything of Foo here (it is inherited already)
private:
    int m_no;
}

第二部分

另一种方法是遵循open-closed principle(决定如果必须以越来越多的数量调用方法,那么Foo有责任实现它,并添加template method implementation) :

class Foo
{
public:
    // public interface for methodA, accessible to clients
    void methodA(const char* path);

protected:

    virtual void methodA_impl(int no, const char* path) = 0;
private:
    int m_no; // private: not accesible to specializations
};

void Foo::methodA(const char* path)
{
    methodA_impl(m_no++, path);
}

class Bar: public Foo
{
    // ... 
protected:
    void methodA_impl(int no, const char* path) override;
}

void Bar::methodA_impl(int no, const char* path)
{
    // Bar-speciffic implementation here
}

这遵循开闭原则,因为“每次通话必须增加数量”要求是固定的,不能被覆盖 特。

Foo特化的客户端无法更改方法调用方法(它总是被正确调用),并且您具有所需的虚方法行为。

答案 1 :(得分:0)

当基类是纯虚拟的时,您希望实例化的子类需要在实例化之前完全实现纯虚方法。但你可以创建一个默认实现方法的“中间”层,然后继承这些方法。

注意:请记住使用虚拟析构函数创建非最终类。

答案 2 :(得分:0)

该类Foo的重点已定义,因此所有派生类必须覆盖所有纯虚方法。

最明显的解决方法是向任何提供课程Foo的人抱怨并让他们提供合理设计的基类。以这种方式定义类是绝对糟糕的设计,除非显然必须覆盖所有虚函数。它也是一个糟糕的设计(因为有些情况下结果是未定义的行为)有一个没有虚拟析构函数的基类。

如果这是您的设计,请重新设计整个类层次结构。说真的,设计很差。

但是,可以简单地从Foo派生另一个类并覆盖所有必需的成员函数。例如;

class FooIntermediary : public Foo
{
    virtual void methodA(int no, const char* path);
    virtual void methodB(const char* name, const char* path);
    virtual void methodC(const char* name, const char* path);

};

void FooIntermediary::methodA(int no, const char *path)
{
    Foo::methodA(no, path);
}

void FooIntermediary::methodB(const char *name, const char *path)
{
    Foo::methodB(name, path);
}

// etc

然后,任何派生自FooIntermediary的类都将被强制覆盖Foo未覆盖的FooIntermediary中的任何继承函数。

你可以找到另一个派生自Foo的类,它可以被实例化,并且(除了你寻求的特定变化之外)你需要的所有行为。根据定义,该类将覆盖所有继承的抽象函数。因此,从中派生一个类,并仅覆盖您需要的虚函数。