将 C++ 嵌套类分离到它们自己的头文件中
Posted
技术标签:
【中文标题】将 C++ 嵌套类分离到它们自己的头文件中【英文标题】:Seperating C++ Nested Classes into their Own Header Files 【发布时间】:2021-12-25 01:48:07 【问题描述】:刚接触这个网站和 C++,但希望得到大家的指导。
我有一个非常有趣的项目想法来学习 C++ 深入挖掘 API、类、引用等,目前我有一个工作示例代码,其中所有内容都存在于 main.cpp 文件中。我面临的问题是,当我将类(内部和外部)移动到它们各自的头文件时,代码不再编译。
嵌套类的原因是 OuterAPI 作为 API 的主要入口点,并且有许多较低级别的 API,然后可以在其下访问(人员、许可证、角色等)。这样,API 用户只需为 OuterAPI 创建一个对象,然后为底层资源和方法创建点符号。
这是 main.cpp 中的工作示例
#include <iostream>
#include <nlohmann/json.hpp>
#include <cpr/cpr.h>
using json = nlohmann::json;
class OuterAPI
private:
class InnerAPI
private:
OuterAPI& api;
public:
InnerAPI(OuterAPI& a) :api(a)
json get()
cpr::Response r = cpr::Get(
cpr::Url api.baseUrl + "resource" ,
cpr::Bearer api.token
);
return json::parse(r.text)
;
std::string token;
std::string baseUrl = "";
public:
InnerAPI people;
OuterAPI(std::string t) : token(t), people(*this)
;
int main(int argc, char** argv)
std::string token = "";
OuterAPI api(token);
json jsonData = api.people.get();
std::cout << jsonData.dump(4) << std::endl;
return 0;
这是我将所有内容移至相应的头文件/cpp 文件
OuterAPI.h
#pragma once
class OuterAPI
private:
class InnerAPI;
std::string token;
std::string baseUrl = "";
public:
OuterAPI(std::string t);
~OuterAPI();
InnerAPI* people;
;
外部API.cpp
#include "WebexAPI.h"
#include "PeopleAPI.h"
OuterAPI::OuterAPI(std::string t) : token(t)
people = new InnerAPI(*this);
OuterAPI::~OuterAPI() delete people;
InnerAPI.h
#pragma once
#include <nlohmann/json.hpp>
#include <cpr/cpr.h>
#include "OuterAPI.h"
using json = nlohmann::json;
class OuterAPI::InnerAPI
private:
OuterAPI& api;
public:
InnerAPI(OuterAPI& a);
json get();
;
InnerAPI.cpp
#include "InnerAPI.h"
OuterAPI::InnerAPI::InnerAPI(OuterAPI& a) : api(a)
json OuterAPI::InnerAPI::get()
cpr::Response r = cpr::Get(
cpr::Url api.baseUrl + "resource" ,
cpr::Bearer api.token
);
return json::parse(r.text);
main.cpp (finally) - 这是在 api.people.get()
"expression must have class type but has type "OuterAPI::InnerAPI *
" 处发生编译器错误的地方
int main(int argc, char** argv)
std::string token = "";
OuterAPI api(token);
json jsonData = api.people.get(); // COMPILER ERROR "expression must have class type but has type "OuterAPI::InnerAPI *"
std::cout << jsonData.dump(4) << std::endl;
return 0;
据此,我认为问题与我必须将 InnerAPI
对象 people
定义为 OuterAPI
内部的指针有关,但从这里我似乎无法解决。
另外,请随时批评我的设计,就像我说我是 C++ 新手,所以想确保我能做好。谢谢。
【问题讨论】:
“代码不再编译。” 当代码编译失败时,您会收到一条错误消息。该特定信息很重要!它描述了需要解决的问题。你能edit这个问题包含我认为你不理解的错误信息吗?OuterAPI.h
缺少标头保护,它也有 #include
用于它不使用的标头,并且缺少 #include
用于它确实使用的东西。 (在许多 C++ 书籍中,如何组织代码经常被忽视或掩盖。)
@DrewDormann,我将编译器错误消息放在“main.cpp”的代码 sn-p 中,但我可以更新为更具体。但是对你来说, api.people.get() 有错误“表达式必须具有类类型但类型为“OuterAPI::InnerAPI *”
@Eljay 我确实在头文件的顶部有一次#pragma,只是在代码 sn-p 中错过了它,对此感到抱歉。对包含的良好调用,但即使移动它们似乎也不会改变编译器错误
【参考方案1】:
在OuterAPI*
中,您已将people
声明为InnerAPI*
类型的成员。
您可以使用api.people->get()
调用您的API,也可以将成员设为InnerAPI
。
编辑:
似乎除了指针之外的错误来自您处理文件包含的方式。我设法得到了working version on REPL.it。我做了一些细微的调整,这样我就不必把两个库都集中在它的要点上。这里是:
OuterAPI.h
#pragma once
#include <string>
class OuterAPI
private:
class InnerAPI;
std::string token;
std::string baseUrl = "";
public:
OuterAPI(std::string t);
~OuterAPI();
InnerAPI* people;
;
InnerAPI.j
#pragma once
#include "./OuterAPI.h"
class OuterAPI::InnerAPI
private:
OuterAPI& api;
public:
InnerAPI(OuterAPI& a);
std::string get();
;
外部API.cpp
#include "./OuterAPI.h"
#include "./InnerAPI.h"
OuterAPI::OuterAPI(std::string t) : token(t)
people = new InnerAPI(*this);
OuterAPI::~OuterAPI() delete people;
InnerAPI.cpp
#include "./OuterAPI.h"
#include "./InnerAPI.h"
OuterAPI::InnerAPI::InnerAPI(OuterAPI& a) : api(a)
std::string OuterAPI::InnerAPI::get()
return api.baseUrl + "resource";
【讨论】:
感谢您的反馈。我尝试了api.people->get()
,但随后收到错误pointer to incomplete class type "OuterAPI::InnerAPI" is not allowed
,您能否详细说明“使成员成为InnerAPI”在实现方面的样子?最初我试图在没有指针的情况下定义people
,但由于类型不完整而出现错误。
你只转发声明了吗? (例如:class Foo;
是前向声明,class Foo ;
是定义。
一边测试一边,我意识到您的问题的其余部分可能是您如何在彼此中包含文件。我添加了一份工作草案。
非常感谢,这实际上有助于我现在理解,因为我确实对指针和包含感到困惑。你帮助我确定了一些我必须阅读的领域。我也很感谢您花时间对此进行测试。我测试了一个也能够让代码正确编译。如果我可以再问一个关于包含的问题,对于main.cpp
,我必须同时包含Outer.h
和Inner.h
才能使其正常工作。是否有解决方案只允许将 Outer.h
文件包含在 main 中?
明白。非常感谢所有的帮助【参考方案2】:
确保在您打算这样做的每个文件中都包含您打算使用的所有内容。 将声明和定义分开是很常见的。 这是一种减少大型项目编译时间的方法。 谢天谢地,modules 很快就会™ 让链接成为过去。
要解决错误消息:您将people
声明为OuterAPI
类的原始成员指针...您无法通过使用operator .
的指针访问成员,您需要使用operator ->
。
【讨论】:
我要感谢您 ViralTaco_ 的帮助。以上是关于将 C++ 嵌套类分离到它们自己的头文件中的主要内容,如果未能解决你的问题,请参考以下文章