我正在尝试学习如何正确分离类标头和代码

I'm trying to learn how to properly separate class header and code

本文关键字:分离 代码 何正确 学习      更新时间:2023-10-16

我有一个大学时做的"有效"的课堂项目,但没有正确构建。

它有一个日期类和一个人员类。

在我的"工作"代码中,所有类数据(构造函数、成员和函数)都包含在每个类的单个头文件中(每个类的单独文件)。

该程序将文本文件数据(人物、总统和演员)加载到矢量中,在控制台上对数据进行排序、过滤和打印,并将其保存到文件中。

在 Person 类构造函数(和函数)中,Date 类为"birthdate"对象实例化。然后在程序中使用生日。

我遇到的问题是这样的:

如果所有类代码都在每个类的头文件中,并且我使 Date 成为 Person 的"父"类,我可以轻松地在 Person 构造函数和成员中实例化"Date"。但是,如果我不做这两件事,那么"人"对"日期"一无所知,也无法从日期实例化任何东西。

如果我在 Person.h 中使用 #include"Date.h",这会产生更多问题并且也不起作用。

当然,"Date"不是"Person"的合适父类,但这是我破解代码使其工作的唯一方法,哈哈。当我几年前在大学里第一次编写代码时,我从来没有想过如何正确地划分类代码,以便它能够编译和运行。头文件中包含所有类代码的"工作代码"是我的黑客。我想学习如何以正确的方式做到这一点。

我已经粘贴了下面的最低限度的例子,说明什么"有效",什么无效。任何使此代码适用于分为头文件和.cpp文件的类的提示将不胜感激。

什么有效:

class Date {
    private:
        int month;
        int day;
        int year;
    public:
        Date::Date() {}
        virtual ~Date() {}
        Date( int aMonth, int aDay, int aYear ) {
            this->month = aMonth;
            this->year = aYear;
            this->day = aDay;
        }
        // "Getter" functions for the Date class
        int getMonth(){return this->month;}
        int getYear() {return this->year;}
        int getDay() {return this->day;}
        // "Setter" functions for the Date class
        void setDay( int aDay ){ this->day = aDay; }
        void setMonth( int aMonth )  { this->month = aMonth; }
        void setYear( int aYear ) { this->year = aYear; }
};
class Person : public Date{
    private:
        string title;
        string firstName;
        string lastName;
        Date birthDate;
    public:
        Person::Person() {}
        Person(string title, string firstName, string lastName, Date birthDay);
        virtual ~Person() {}
        //"Getter" functions for the Person class
        string getTitle() { return title; }
        string getFirstName() { return firstName; }
        string getLastName() { return lastName; }
        Date getBirthDay() { return birthDate; }
        //"Setter" functions for the Person class
        void setTitle(string Title) { this->title = Title; }
        void setFirstName(string fName) { this->firstName = fName; }
        void setLastName (string lName) { this->lastName = lName; }
        void setBirthday (Date aBirthday) { this->birthDate = aBirthday; }
};

什么不起作用(不编译):

日期.h

class Date {
    private:
        int month;
        int day;
        int year;
    public:
        Date();
        virtual ~Date() {}
        Date( int aMonth, int aDay, int aYear );
        //Getters and setters
        int getMonth();
        int getYear() ;
        int getDay();
        void setDay( int aDay );
        void setMonth( int aMonth ) ;
        void setYear( int aYear ) ;
};

日期.cpp

#include "Date.h"
Date::Date() {}
Date::Date( int aMonth, int aDay, int aYear ) {
    this->month = aMonth;
    this->year = aYear;
    this->day = aDay;
}
int Date::getMonth(){return this->month;}
int Date::getYear() {return this->year;}
int Date::getDay()  {return this->day;}
//"Setter" functions for the Date class
void Date::setDay( int aDay ){ this->day = aDay; }
void Date::setMonth( int aMonth )  { this->month = aMonth; }
void Date::setYear( int aYear ) { this->year = aYear; }

人.h

#include <string>
class Person{
    private:
        string title;
        string firstName;
        string lastName;
        Date birthDate;
    public:
        //Person::Person() {}
        Person(string title, string firstName, string lastName, Date birthDay); 
        //"Getter" functions for the Person class
        string getTitle() { return title; }
        string getFirstName() { return firstName; }
        string getLastName() { return lastName; }
        Date getBirthDay() { return birthDate; }
        //"Setter" functions for the Person class
        void setTitle(string Title) { this->title = Title; }
        void setFirstName(string fName) { this->firstName = fName; }
        void setLastName (string lName) { this->lastName = lName; }
        void setBirthday (Date aBirthday) { this->birthDate = aBirthday; }
    };

人.cpp

#include "Person.h"
#include <iostream>
using namespace std;
//Person class constructor with 0 arguments
Person::Person(string atitle, string afirstName, string alastName, Date abirthDay) {
    title = atitle,
          firstName = afirstName,
          lastName = alastName,
          birthday = abirthDay)
}
//"Getter" functions for the Person class
string Person::getTitle() { return title; }
string Person::getFirstName() { return firstName; }
string Person::getLastName() { return lastName; }
Date Person::getBirthDay() { return birthDate; }
//"Setter" functions for the Person class
void Person::setTitle(string Title) { this->title = Title; }
void Person::setFirstName(string fName) { this->firstName = fName; }
void Person::setLastName (string lName) { this->lastName = lName; }
void Person::setBirthday (Date aBirthday) { this->birthDate = aBirthday; }

操作系统说明

我在 Windows 7 PC 上使用 MS Visual Studio 2012 Update 4。

若要防止重定义错误,请将包含保护添加到头文件。要便于携带,请使用:

#if !defined(THE_HEADER_NAME_H)
#define THE_HEADER_NAME_H
// Usual code and declarations here.
#endif

在 Visual Studio 中,您可以使用:

#pragma once
// Usual code and declarations here.

在标头中,不要写入(在全局范围级别)

using namespace XXXXX

因为这将导致包括您的文件在内的所有文件也使用他们可能不希望强加给他们的命名空间 XXXXX。如果使用命名空间中的类型,请使用命名空间键入整个类型名称,因此请使用:

std::string getTitle()

(在 cpp 文件中,您可以在任何 #includes 后使用"使用命名空间 XXXXX")

我直言,您有 2 个问题。

首先是斯科特·朗厄姆的回答将解决的警卫问题。

第二个是命名空间问题。

我假设在您的工作源代码中,您有(直接间接通过 stdafx.h 或其他包括):

#include <string>
using namespace std;

不建议在.h头文件中using namespace std;...但这意味着您应该使用 std::string 而不是 string

日期.h

class Date {
    private:
        int month;
        int day;
        int year;
    public:
        Date::Date() { }                                                //Date class constructor with 0 arguments
        virtual ~Date() {}                                              //Date class destructor
        Date( int aMonth, int aDay, int aYear ) {                       //Date class constructor with 3 arguments
            this->month = aMonth;                                       // Set the private member data with the argument data
            this->year = aYear;
            this->day = aDay;
            }       
        //"Getter" functions for the Date class
        int getMonth(){return this->month;}                             
        int getYear() {return this->year;}
        int getDay() {return this->day;} 
        //"Setter" functions for the Date class
        void setDay( int aDay ){ this->day = aDay; }                    
        void setMonth( int aMonth )  { this->month = aMonth; }  
        void setYear( int aYear ) { this->year = aYear; }
};

person.h (字符串 -> std::字符串和删除方法实现)

#include <string>
#include "Date.h"
class Person : public Date{
private:                                                                //Private data members
    std::string title;
    std::string firstName;
    std::string lastName;
    Date birthDate;
public:
    Person::Person() {}                                                 //Person class constructor with 0 arguments
    Person(std::string title, 
        std::string firstName, 
        std::string lastName, 
        Date birthDay);                                                 //Person class constructor with 4 arguments
    virtual ~Person(){}                                                 //Person class destructor
    //"Getter" functions for the Person class
    std::string getTitle();
    std::string getFirstName();
    std::string getLastName();
    Date getBirthDay();
    //"Setter" functions for the Person class
    void setTitle(std::string Title);
    void setFirstName(std::string fName);
    void setLastName (std::string lName);
    void setBirthday (Date aBirthday);
};

人.cpp(固定包含和构造函数)

#include <string>
#include "Person.h"
#include <iostream>
using namespace std;
//Person class constructor with 0 arguments
Person::Person(string atitle, string afirstName, string alastName, Date abirthDay) {
    title = atitle,
          firstName = afirstName,
          lastName = alastName,
          birthDate = abirthDay;
}
//"Getter" functions for the Person class
string Person::getTitle() { return title; }
string Person::getFirstName() { return firstName; }
string Person::getLastName() { return lastName; }
Date Person::getBirthDay() { return birthDate; }
//"Setter" functions for the Person class
void Person::setTitle(string Title) { this->title = Title; }
void Person::setFirstName(string fName) { this->firstName = fName; }
void Person::setLastName (string lName) { this->lastName = lName; }
void Person::setBirthday (Date aBirthday) { this->birthDate = aBirthday; }

它甚至可以在没有防护装置的情况下使用,但无论如何,护卫都是一种很好的做法。

事实上,由于Date.h包含在Person.h它确实应该有一个防护装置 - 为简单起见,此处未显示