抽象基类或派生类中的类变量

Class variable in abstract base class or derived class?

本文关键字:类变量 派生 基类 抽象      更新时间:2023-10-16

我有一个抽象类,该类具有一个可变的 owner_,它是字符串。每个派生的类都声明此变量的名称。在抽象基类中拥有变量是更好的练习,还是我可以在派生类中多次多次实现它?

#include <string>
#include <iostream>
class Pet
{
    public:
        Pet(const std::string& owner) : owner_(owner) {}
        virtual ~Pet() = 0;
        virtual void print_status() = 0;
    protected:
        const std::string owner_;
};
Pet::~Pet() {}
class Dog : public Pet
{
    public:
        Dog(const std::string& owner) : Pet(owner) {}
        ~Dog() {};
        void print_status()
        {
            std::string s = "Woof! My owner is ";
            s += owner_;
            std::cout << s << std::endl;
        }
    // Or better here?
    // private:
    //     const std::string owner_;
};
class Cat : public Pet
{
    public:
        Cat(const std::string& owner) : Pet(owner) {}
        ~Cat() {};
        void print_status()
        {
            std::string s = "Meow! My owner is ";
            s += owner_;
            std::cout << s << std::endl;
        }
    // Or better here?
    // private:
    //     const std::string owner_;
};
int main()
{
    Dog dog("Mario");
    dog.print_status();
    Cat cat("Luigi");
    cat.print_status();
    return 0;
}

imo,这正是抽象基类的目的:在继承层次结构中为接口提供常见的实现。
我将走得更远,甚至将接口与抽象基类分开:

struct IPet {
    virtual ~IPet() = {}
    virtual void print_status() = 0;
    virtual const std::string& get_owner() const = 0;
};
class Pet : public IPet
{
public:
    Pet(const std::string& owner) : owner_(owner) {}
    virtual const std::string& get_owner() const { return owner_; }
    virtual ~Pet() {} // = 0; Don't declare the destructor as pure virtual function
    virtual void print_status() = 0;
protected:
    std::string owner_;
};

您可能需要使用摘要来迫使您的孩子类实现该方法,但不一定定义其中的任何内容。如果您故意使用它们,则将所有者在基类中,但是各自方法中的不同内容是正确的。

摘要方法正在使用,例如,如果您希望所有子类都至少在自己的类中声明该功能,这有时是相应子类的不同行为所需的。

class Pet
{
public:
    Pet(const std::string& owner) :
        owner_(owner) {}
    virtual ~Pet() = 0;
    virtual void print_status() = 0;
protected:
    const std::string owner_;
};
Pet::~Pet() {}
class Dog : public Pet
{
private:
    int age;
public:
    Dog(const std::string& owner, int age) :
        Pet(owner), age(age) {}
    ~Dog() {};
    void print_status(){
        std::cout << "Woof! My owner is " << this->owner_ << 
            " and my age is " << this->age << "nn";
    }
};
class Cat : public Pet
{
public:
    Cat(const std::string& owner) :
        Pet(owner) {}
    ~Cat() {};
    void print_status() {
        std::cout << "Miaw, my owner is " << this->owner_ << 'n';
    }
};
int main()
{
    Dog dog("Mario", 25);
    dog.print_status();
    Cat cat("Luigi");
    cat.print_status();
    system("pause");
    return 0;
}