从抽象基类派生的C ++包装器类,并在另一个也从抽象基类派生的类中调用方法

时间:2018-08-03 11:04:43

标签: c++ inheritance abstract-class wrapper

我有一个名为Animal的抽象类和一个名为cow的派生类。

CowAnimal中提供了纯虚函数的定义。

我想创建一个名为AnimalWrapper的类,该类继承自Animal。我希望方法AnimalWrapper.speak()仅调用cow.speak()

我是否只需要在animalwrapper类中引用cow对象,以便我可以调用非静态方法说话?

我该怎么做?

     #include<iostream>
#include<cstdlib>

using namespace std;

#include <string>
class Animal // This Animal is an abstract base class
{

public:
    Animal(){};

    virtual const char* speak() = 0; //pure virtual function
};

class Cow: public Animal
{
public:
    Cow(){};

    virtual const char* speak() {
        cout << "I am a cow" << endl;
        return "Moo     ";
    }
};

class AnimalWrapper: public Animal
{
public:
    AnimalWrapper(){}

    virtual const char* speak() {

        cout << "Calling cow class speak() method" << endl;
        //Call Cow::speak()

        return "Moo";
    }
};


int main()
{
    AnimalWrapper AnimalWrapper_obj ;
    std::cout << AnimalWrapper_obj.speak() << '\n';
}

2 个答案:

答案 0 :(得分:1)

假设您要扩展使用中的API,但不能对其本身进行修改,那么我得出结论,您想提供一个并行层次结构:

namespace wrapped
{
class Animal
{
public:
    virtual ~Animal();
    virtual std::string speak();
};

class Cow : public Animal
{
public:
    std::string speak() override;
    unsigned int giveMilk() { return 77; }
};
}

namespace wrapping
{
class Animal
{
protected:
    wrapped::Animal& animal;
    Animal(wrapped::Animal& animal)
        : animal(animal)
    { }
public:
    virtual ~Animal() { }

    // does not need to be virtual, we can profit from
    // polymorphism of referred object...
    //
    // still it CAN be virtual, if you want to allow derived
    // wrappers as well to modify the inherited speak!
    std::string speak()
    {
        return animal.speak();
    }
};

class Cow : public Animal
{
public:
    Cow(wrapped::Cow& cow)
        : Animal(cow)
    { }

    // speak is inherited

    unsigned int giveMilk()
    {
        // don't need dynamic cast as we passed a reference
        // to cow object to base class constructor...
        return static_cast<wrapped::Cow&>(animal).giveMilk();
    }
};
}

如果CowAnimal继承 可以使用的变体可以使您编写的代码更少:

namespace wrapping
{
class Animal : private virtual wrapped::Animal
{
public:
    using wrapped::Animal::speak;
};

class Cow : public Animal, private wrapped::Cow
{
public:
    using wrapped::Cow::speak;
};
}

但是,如果Cow不是虚拟继承的,则您的包装Cow将继承wrapped::Animal的两个实例,这将导致许多问题,此处暂不讨论。

但是,如果您在speak中覆盖wrapping::animal,则需要在wrapping::Cow中提供 finaloverrer 来解决两个继承的覆盖的变体之间的歧义speak

实际上,您可以可以公开地从已包装的基类继承,那么您将不再需要using声明(尽管仍然存在最终的替代者问题),但这将允许包装类和包装类,您很可能想避免。

答案 1 :(得分:0)

根据您的评论,这里是一个AnimalWrapper类的示例,该类使用move语义获取Cow实例的外部引用。由于它是移动构造函数,而不是复制构造函数,因此在使用原始对象时应格外小心。

如果要保留Cow的原始实例,则可能需要复制构造函数(但您将复制Cow实例)。

您还可以将指针或引用存储在类Cow * cowInstanceCow& cowInstance中),但是您可能会以悬空的指针/引用结尾(因此在这里使用了移动语义)。 >

#include<iostream>
#include<cstdlib>
#include <memory>
// using namespace std; // <= Using namespace std is considered bad practice

#include <string>
class Animal // This Animal is an abstract base class
{

public:
    Animal(){}
    virtual ~Animal() {} // Do some research about the difference between virtual and non virtual destructor in C++
    virtual std::string speak() = 0; //pure virtual function
};

class Cow: public Animal
{
public:
    Cow(){}
    Cow(const Cow& cow) = delete;
    Cow(Cow&& _cow) {std::cout << "Move constructor " << std::endl;}
    virtual ~Cow() {}
    // virtual const char* speak() { // <= Use std::string in c++
    virtual std::string speak() {
        ++m;
        std::cout << "I am a cow : "<< m << std::endl;
        return std::string("Mooo");
    }

private: 
    int m = 0;
};

class AnimalWrapper // : public Animal // <= This is unnecessary
{
public:

    AnimalWrapper(std::unique_ptr<Cow> _cow) : cowInstance((std::move(_cow))) { 
    }

    std::string speak() {
        std::cout << "Calling cow class speak() method" << std::endl;
        return cowInstance->speak();
    }
private:
    std::unique_ptr<Cow> cowInstance;
};


int main()
{
    std::unique_ptr<Cow> cow(new Cow);
    cow->speak();
    std::cout << "Hello, world!" << std::endl;
    AnimalWrapper AnimalWrapper_obj(std::move(cow));
    std::cout << AnimalWrapper_obj.speak() << '\n';
}

由于您要解决的问题对我来说仍然不清楚,因此这可能不是理想/完美的解决方案。但是,这只是您根据我的理解所提出的要求的一个示例。