如何在 C++ 中正确扩展类并编写其头文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19079534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:29:53  来源:igfitidea点击:

How to correctly extend a class in C++ and writing its header file?

c++compilationheader

提问by Angelo

Note: I've edited my old question to be as clear as possible.

注意:我已经编辑了我的旧问题,使其尽可能清晰。

I've got a third party library named person.liband its header person.h. This is my actual project structure and it compiles and runs perfectly.

我有一个名为的第三方库person.lib及其 header person.h。这是我的实际项目结构,它可以完美地编译和运行。

Actual Structure:

实际结构:

main.cpp

主程序

#include <iostream>
#include <time.h>
#include <ctype.h>
#include <string>
#include "person.h"
using namespace person;
using namespace std;

class Client : public Person 
{
    public:
        Client();   
        void onMessage(const char * const);
    private:
        void gen_random(char*, const int);
};

Client::Client() {
    char str[11];
    gen_random(str, 10);
    this->setName(str);
}

void Client::onMessage(const char * const message) throw(Exception &) 
{
    cout << message << endl;
}

void Client::gen_random(char *s, const int len) {
    //THIS FUNCTION GENERATES A RANDOM NAME WITH SPECIFIED LENGTH FOR THE CLIENT
}

int main()
{
    try
    {
        Person *p = new Client;
        p->sayHello();
    }
    catch(Exception &e)
    {
        cout << e.what() << endl;
        return 1;
    }
    return 0;
}

Now, I want to refactor my code by dividing the declaration of my Clientclass from its definition and create client.hand client.cpp. PAY ATTENTION: sayHello()and onMessage(const * char const)are functions of the person library.

现在,我想通过将我的Client类的声明与其定义分开来重构我的代码并创建client.hclient.cpp注意sayHello()onMessage(const * char const)人库的功能。

Refactored Structure:

重构结构:

main.cpp

主程序

#include <iostream>
#include "client.h"
using namespace person;
using namespace std;

int main()
    {
        try
        {
            Person *p = new Client;
            p->sayHello();
        }
        catch(Exception &e)
        {
            cout << e.what() << endl;
            return 1;
        }
        return 0;
    }

client.cpp

客户端

#include "client.h"
using namespace person;
using namespace std;

Client::Client() {
    char str[11];
    gen_random(str, 10);
    this->setName(str);
}

void Client::onMessage(const char * const message) throw(Exception &) 
{
    cout << message << endl;
}

void Client::gen_random(char *s, const int len) {
    //THIS FUNCTION GENERATES A RANDOM NAME WITH SPECIFIED LENGTH FOR THE CLIENT
}

client.h

客户端.h

#ifndef CLIENT_H
#define CLIENT_H
#include <time.h>
#include <ctype.h>
#include <string>
#include "person.h"

class Client : public Person 
{
    public:
        Client();   
        void onMessage(const char * const);
    private:
        void gen_random(char*, const int);
};
#endif

As you can see, I've simply created a client.hin wich there's the inclusion of the base class person.h, then I've created client.cppin wich there's the inclusion of client.hand the definitions of its functions. Now, the compilation gives me these errors:

正如您所看到的,我只是在其中创建了一个client.h包含基类的内容person.h,然后我在其中创建client.cpp了一个包含client.h其功能的内容和定义。现在,编译给了我这些错误:

error C2504: 'Person': base class undefined     client.h    7   1   Test
error C2440: 'inizialization': unable to convert from 'Client *' to 'person::impl::Person *'   main.cpp 15  1   Test
error C2504: 'Person': base class undefined     client.h    7   1   Test
error C2039: 'setName': is not a member of 'Client'  client.cpp 8   1   Test
error C3861: 'sendMessage': identifier not found    client.cpp  34  1   Test

It's a merely cut&copy refactoring but it doesn't work and I really don't understand WHY! What's the solution and why it gives me these errors? Is there something about C++ structure that I'm missing? Thank you.

这只是一个简单的剪切和复制重构,但它不起作用,我真的不明白为什么!解决方案是什么,为什么会出现这些错误?有没有我遗漏的关于 C++ 结构的东西?谢谢你。

回答by enhzflep

Here's a dog-n-bird implementation (ruff ruff, cheep cheep) cLawyer is defined and implemented in main.cpp, while cPerson and cClient are defined in their own header files, implemented in their own cpp file. A better approach would store the name of the class. Then, one wouldn't need to overload the speak method - one could simply set the className in each derived copy. But that would have provided in my estimates, a less useful example for you.

这里是dog-n-bird的实现(ruff ruff, cheep cheep)cLawyer是在main.cpp中定义和实现的,而cPerson和cClient是在自己的头文件中定义的,在自己的cpp文件中实现。更好的方法是存储类的名称。然后,就不需要重载 speak 方法 - 只需在每个派生副本中设置 className 即可。但这会在我的估计中提供,对您来说是一个不太有用的例子。

main.cpp

主程序

#include <cstdio>
#include "cClient.h"

class cLawyer : public cPerson
{
    public:
        cLawyer() : cPerson() {}
        ~cLawyer() {}
        void talk(char *sayWhat){printf("cLawyer says: '%s'\n", sayWhat);}
};

int main()
{
    cPerson newPerson;
    cClient newClient;
    cLawyer newLawyer;

    newPerson.talk("Hello world!");
    newClient.talk("Hello world!");
    newLawyer.talk("Hello $$$");

    return 0;
}

cPerson.h

cPerson.h

#ifndef cPerson_h_
#define cPerson_h_

class cPerson
{
    public:
        cPerson();
        virtual ~cPerson();
        virtual void talk(char *sayWhat);
    protected:
    private:
};

#endif // cPerson_h_

cPerson.cpp

cPerson.cpp

#include "cPerson.h"
#include <cstdio>
cPerson::cPerson()
{
    //ctor
}

cPerson::~cPerson()
{
    //dtor
}

void cPerson::talk(char *sayWhat)
{
    printf("cPerson says: '%s'\n",sayWhat);
}

cClient.h

客户端.h

#ifndef cClient_h_
#define cClient_h_

#include "cPerson.h"

class cClient : public cPerson
{
    public:
        cClient();
        virtual ~cClient();
        void talk(char *sayWhat);
    protected:
    private:
};

#endif // cClient_h_

cClient.cpp

客户端.cpp

#include "cClient.h"
#include <cstdio>

cClient::cClient()
{
    //ctor
}

cClient::~cClient()
{
    //dtor
}

Output

输出

cPerson says: 'Hello world!'
cClient says: 'Hello world!'
cLawyer says: 'Hello $$$'

Suggestions noted above:

上面提到的建议:

//In the cPerson class, a var
  char *m_className;

//In the cPerson::cPerson constructer, set the var
  m_className = "cPerson";

//Re-jig the cPerson::speak method
void cPerson::speak(char *sayWhat)
{
  printf("%s says: '%s'\n", m_className, sayWhat);
}

// EDIT: *** remove the speak methods from the cClient and cLawyer classes ***

//Initialize the clas name apporpriately in derived classes
//cClient::cClient
  m_className = "cClient";


//Initialize the clas name apporpriately in derived classes
//cLaywer::cLaywer
  m_className = "cLawyer";

回答by Shimon Rachlenko

You are declaring the class Client twice - once in the .hfile and once in .cpp. You only need to declare it in the .hfile.
You also need to put the using namespace person;to the .hfile.
If class Person is in namcespace person, use the person::Personto access it.

您将类 Client 声明两次 - 一次在.h文件中,一次在.cpp. 你只需要在.h文件中声明它。
你也需要把using namespace person;.h文件。
如果类 Person 在名称空间中,则使用person::Person来访问它。

The client.cppmust contain definitions only!

client.cpp只能包含定义!

I think for the linker the class Client defined in client.h and class Client defined in client.cpp are different classes, thus it cannot find the implementation of Client::Client(). I purpose to remove the declaration of class Client from the client.cpp and leave there only definitions of functions:

我认为对于链接器,client.h 中定义的类 Client 和 client.cpp 中定义的类 Client 是不同的类,因此它找不到 Client::Client() 的实现。我的目的是从 client.cpp 中删除类 Client 的声明,只留下函数的定义:

// client.cpp

#include <time.h>
#include <ctype.h>
#include <string>
#include "client.h"
using namespace std;

Client::Client()
{
    //DO STUFF
}

void Client::onMessage(const char * const message)
{
    //DO STUFF
}


void Client::gen_random(char *s, const int len) {
    //DO STUFF
}