从基类继承的C ++公共方法无法访问派生类中的私有成员变量

时间:2013-11-04 04:26:11

标签: c++ inheritance private

我有代码:

#include <iostream>
#include <cstdlib>
using namespace std;

class Animal{
private:
    int age;
public:
    Animal() : age(1) {}
    void toString(){
        cout << "Age: " << age << endl;
    }
};
class Cat : public Animal
{
public:
    Cat() : age(5) {}
    /*
    void toString(){
        cout << "Age: " << age << endl;
    }*/
private:
    int age;
};

int main(){
    Cat tom;
    tom.toString();

    system("pause");
    return 0;
}

但是当我运行该程序时, tom 变量的年龄为1,而不是5. toString 是否无法读取年龄变量?如果我们在Cat类中打开/ * * / toString方法,则年龄为5!

(我的英语不太好。谢谢)

3 个答案:

答案 0 :(得分:1)

问题是您在Cat::age构造函数中设置了Cat,而不是Animal::age使用的Animal::toString

Animal::age的可见性更改为受保护。

class Animal {
protected:
    int age;
public:
    Animal() : age(1) {}
    void toString(){
        cout << "Age: " << age << endl;
    }
};

请勿重新声明第二个age(成为Cat::age)。相反,请更改ageAnimal::age)的值。

class Cat : public Animal {
public:
    Cat() {
        age = 5;
    }
};

答案 1 :(得分:1)

问题是Cat正在写age中的Cat变量,而toString()读取age中的Animal变量,其中Animal的构造函数初始化为1

要解决此问题,您可以为Animal提供另一个构造函数,该构造函数接受age参数,该参数用于初始化Animal的{​​{1}}成员变量。

age

UPDATE:另一种解决方案是在class Animal{ private: int age; public: Animal() : age(1) {} Animal(int param_age) : age(param_age) {} // Initialize member variable age with parameter void toString(){ cout << "Age: " << age << endl; } }; class Cat : public Animal { public: Cat() : Animal(5) {} // Call Animal's constructor that set's the age }; 类中添加一个设置其年龄的setter方法。然后,您可以在Animal的构造函数中调用它来设置适当的年龄。

Cat

另一种方法是让class Animal{ private: int age; public: Animal() : age(1) {} void setAge(int age) { this->age = age; } void toString(){ cout << "Age: " << age << endl; } }; class Cat : public Animal { public: Cat() { setAge(5); } }; 的{​​{1}}成员Animal

age

在类定义中删除protected的{​​{1}}变量。尽管它很简单,但这种方法在遇到"brittle base class" problem时会带来更大的风险。因此,我推荐前一种解决方案,因为它不太容易出现上述问题,而恕我直言更好地坚持“针对接口而不是实现”原则。

答案 2 :(得分:0)

尝试:

#include <iostream>
#include <cstdlib>
using namespace std;

class Animal{
private:
    int age;
public:
    Animal(int a = 1)   // Pass in the age as a parameter.
       : age(a)         // Default to 1.
    {}

    // Prefer generic print function rather than toString()
    friend std::ostream& operator<<(std::ostream& s, Animal const& a) {
        return s << "Age: " << a.age << '\n';  // Prefer '\n' rather than endl
                                               // Unless you really want to flush
                                               // the stream (this is not usually
                                               // the case).
    }
};
class Cat : public Animal
{
public:
    Cat()
       : Animal(5)      // Now you can call the base class constructor
    {}                  // And get it to set 5
private:
    // int age;         // don't have a private copy here.
                        // use the one that is available in the base class.


    // Prefer generic print function rather than toString()
    friend std::ostream& operator<<(std::ostream& s, Cat const& a)
    {
        // Print Cat
        // Then use the Animal priting function to print more information about the object.
        return s << "A Cat: " << static_cast<Animal const&>(*a);
    }
};

int main(){
    Cat tom;

    // tom.toString(); // Don't use a toString() method.
                       // overload operator<< to print to a stream.
                       // If you want to convert to a string the just print
                       // to a string stream.

    std::cout << tom;

    system("pause");
    return 0;
}