C ++中的派生类

时间:2011-10-11 15:41:57

标签: c++ derived-class

我有一个家庭作业问题:

从基类Student设计派生类GraduateStudent。它添加了一个名为Advisor的数据成员来存储学生论文顾问的名称。提供构造函数,析构函数,访问器和修改器函数。该类重写年份函数,使用下面的图表,根据完成的小时数返回两个字符串中的一个(“Masters”或“PhD”)。

小时年 < = 30大师

(大于)30 PhD

我写过:

using namespace std;


class Student
{
public:
    Student( string s = "", int h = 0);
    ~Student();
    string getName() const;
    int getHours() const;
    void setName(string s);
    void setHours (int h);
    string year () const;
private:
    string name;
    int hours;

};

class GraduateStudent: private Student
{
public:
    GraduateStudent(string s = "", int h=0, string advisor=""); //constructor
    ~GraduateStudent(); //destructor
    string getAdvisor();
    void setAdvisor(string advisor);
    //Class overrides??

private:
    string Advisor;
}

班级学生上了,我加入了研究生派生班。

我的问题是,如果我已正确设置派生类。我的第二个问题是如何在没有if语句的情况下覆盖year函数?我试图使用那些语句,但编辑给了我错误,我怀疑它是一个头文件。

5 个答案:

答案 0 :(得分:4)

如果在派生类中声明一个具有相同名称的函数,它会隐藏基类中具有相同名称的所有函数。

所以只需添加:

  

string year()const;

再次对你的派生类隐藏你的基类功能。

请注意,这是隐藏功能而不是覆盖。对于重写,您需要在Base类中将该函数声明为virtual。这就是Q要求的:

你的基类应该有:

  

虚拟字符串year()const;

您在派生类中进一步声明它,然后适当地为它定义它。


私人继承在这里不是一个好主意,因为,
使用Private Inheritance,Base类的所有成员都将成为派生类的私有成员。

上面的规则意味着你不能调用(在Derived类的对象上)任何只在Base类中实现而在Derived类中没有实现的方法,这不是你想要实现的是我的猜测。

答案 1 :(得分:4)

你被“给予”的学生班级并没有真正写好,以正确地允许覆盖年份功能。一般用例场景(您在容器中保存学生对象将无法正常工作)。

所以,修复(正确):

// Generally, poor practice to have a using namespace
// directive in a header file, instead just properly 
// scope your variables (as below)
// using namespace std;

class Student
{
public:
    Student( std::string s = "", int h = 0);

    // Virtual desctructors allow you to properly free derived
    // classes given a base class pointer
    virtual ~Student();

    std::string getName() const;
    int getHours() const;
    void setName(std::string s);
    void setHours (int h);

    // This function needs to be virtual to be overridable
    virtual std::string year () const;
private:
    std::string name;
    int hours;

};

// Use Public inheritance, after all a
// GraduateStudent IS-A Student
class GraduateStudent: public Student
{
public:
    GraduateStudent(std::string s = "", int h=0, string advisor=""); //constructor
    ~GraduateStudent(); //destructor
    std::string getAdvisor();
    void setAdvisor(string advisor);
    //Class overrides??

    // this function overrides the Student::year() function
    std::string year() const;

private:
    std::string Advisor;
}

另外,为什么您认为在不使用year()语句的情况下需要实现if函数?在这种情况下,这将是适当的事情。

答案 2 :(得分:3)

要覆盖成员函数,您只需在派生类型提供中提供该函数为虚拟的声明和定义。如果它不是虚拟的,则不能覆盖基类中的函数。

因为练习的重点可能是GraduateStudent和其他学生一样,所以你可能想要使用public继承。私有继承通常仅用于提供以而非 is-a 关系实现的

关于类的实现会想到的其他注释:

  • 构造函数应该是显式的,您可能不希望从字符串隐式转换
  • 如果您尝试通过指向Student的指针删除GraduateStudent,则学生析构函数应该是虚拟的(或受保护的)以避免未定义的行为
  • setter中的字符串可能最好通过常量引用传递 - 这里可能会有一些讨论,但超出了你的课程范围(即使用新的 move-semantics ,取决于用法模式任一选项可能更好/更差。
  • 字符串应该通过const引用(在这种情况下无疑是)
  • 在访问器中返回
  • 不修改对象状态的操作应标记为const

答案 3 :(得分:0)

Student的私有继承限制了您对其功能的访问权限。在这种情况下,Public或Protected会更有用。

将year方法声明为virtual将允许您在GraduateStudent类中实现它,并在您以Student身份访问该类时调用它。

答案 4 :(得分:0)

在Student基类virtual string year()中创建虚拟函数。然后在GraduateStudent中提供一个新的定义,用您想要的年份替换年份方法。