Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C++;_C++_C++11_C++14_Friend_Friend Function - Fatal编程技术网

C++ 在C++;

C++ 在C++;,c++,c++11,c++14,friend,friend-function,C++,C++11,C++14,Friend,Friend Function,我正在尝试使用朋友函数。这个函数应该是我所有类的朋友。但我发现了多个错误,其中一些错误是不完整类型。以下是我拥有的文件: main.cpp #include <iostream> #include "my_ClassA.h" #include "my_ClassB.h" #include "my_ClassC.h" #include "my_ClassD.h" int main() { std

我正在尝试使用朋友函数。这个函数应该是我所有类的朋友。但我发现了多个错误,其中一些错误是不完整类型。以下是我拥有的文件:

main.cpp

#include <iostream>
#include "my_ClassA.h"
#include "my_ClassB.h"
#include "my_ClassC.h"
#include "my_ClassD.h"


int main()
{
    std::cout<<"Hello World";
    my_namespace::my_ClassA object1;//this will do some computation and set everything up for object1
    my_namespace::my_ClassB object2(object1);//this object2 will use object1 to further do other computation
    my_namespace::my_ClassC object3(object2);
    
    my_namespace::my_classD object4(object4);    
    //runComputation(object1, object2, object3, object4);

    return 0;
}

#include "my_ClassA.h"

std::vector<std::string> my_namespace::my_ClassA::get_vec(){
    return vec;
}
#include "my_ClassB.h"

std::vector<std::string> my_namespace::my_ClassB::get_vec(){
    return vec;
}
my_namespace::my_ClassB::my_ClassB(my_ClassA temp_objA){
    ;
}
#include "my_ClassC.h"
#include "my_ClassB.h"
std::vector<std::string> my_namespace::my_ClassC::get_vec(){
    return vec;
}
my_namespace::my_ClassC::my_ClassC(my_ClassB temp_objB){
    ;
}
#include "my_ClassD.h"

std::vector<std::string> my_namespace::my_ClassD::get_vec(){
    return vec;
}
#包括
#包括“我的班级A.h”
#包括“my_ClassB.h”
#包括“我的班级C.h”
#包括“我的D.h类”
int main()
{

std::cout不要使用按值返回来避免复制大向量,不要返回常量引用来访问数据,也不要使用非常量引用来修改

例如,标题:

#pragma once 
#include<string>
#include <vector>

//these three includes are for friend function BUT result in error incomplete type
#include "my_ClassB.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
/////////////////////////////////////////////
namespace my_namespace{
    class my_ClassA{
        friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
            
        
        private:
        std::string name;  
        std::vector<std::string> vec;
        public:
            // use this getter to modify inner data by reference 
            std::vector<std::string>& get_vec();

            // use this getter to access data by const referenct
            std::vector<std::string> const & get_vec() const;

    };
    void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
    
}
#pragma一次
#包括
#包括
//这三个包含用于友元函数,但会导致错误不完整类型
#包括“my_ClassB.h”
#包括“我的班级C.h”
#包括“我的D.h类”
/////////////////////////////////////////////
名称空间my_名称空间{
我的班级{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
私人:
std::字符串名;
std::vec;
公众:
//使用此getter通过引用修改内部数据
std::vector&get_vec();
//使用此getter通过常量引用访问数据
std::vector const&get_vec()const;
};
无效运行计算(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}
实施:

#include "my_ClassA.h"

std::vector<std::string>& my_namespace::my_ClassA::get_vec() {
    return vec;
}


std::vector<std::string> const & my_namespace::my_ClassA::get_vec() const {
    return vec;
}
#包括“my_ClassA.h”
std::vector和my_名称空间::my_ClassA::get_vec(){
返回向量;
}
std::vector const&my_名称空间::my_ClassA::get_vec()const{
返回向量;
}

您可能希望将类重构为一系列函数调用:

// class or struct which contains intermediate state
State state;
runComputation1(&state);
runComputation2(&state);
runComputation3(&state);
runComputation4(&state);

这个问题是由于不同文件的循环依赖性造成的。只需对不同的类参数使用转发声明,而不包括头文件,问题就解决了。

创建一个
my_forwards.h
头文件。它包含

名称空间my_名称空间{ 我的班级A; 我的班级是B班; 我的班级是C班; 我的班级D; } (或者在每个头文件的顶部手动写入)

现在,不要在其他标题中包含
my_ClassA.h
。如果在
my_ClassB
中有一个函数体需要定义
my_ClassA
,请将它放在
.cpp
文件中,而不是放在标题中

// my_forwards.h
namespace my_namespace {
  class my_ClassA;
  class my_ClassB;
  class my_ClassC;
  class my_ClassD;
  void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}

// my_ClassA.h
#pragma once
#include<string>
#include <vector>
#include "my_forwards.h"
namespace my_namespace{
  class my_ClassA{
    friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
    
    private:
      std::string name;  
      std::vector<std::string> vec;
    public:
      std::vector<std::string> get_vec();
    };
}

// my_ClassA.cpp
#include "my_ClassA.h"
// include other my_ClassX here if needed, after my_ClassA.h

// implementation of my_ClassA:
std::vector<std::string> my_namespace::my_Class::get_vec() {
  return vec;
}
//my_forwards.h
名称空间my_名称空间{
我的班级A;
我的班级是B班;
我的班级是C班;
我的班级D;
无效运行计算(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}
//我的大学A.h班
#布拉格语一次
#包括
#包括
#包括“my_forwards.h”
名称空间my_名称空间{
我的班级{
friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
私人:
std::字符串名;
std::vec;
公众:
std::vector get_vec();
};
}
//我的班级A.cpp
#包括“我的班级A.h”
//如果需要,在我的A.h类之后,在这里包括其他我的X类
//my_ClassA的实施:
std::vector my_名称空间::my_类::get_vec(){
返回向量;
}
在某些情况下,这可能需要在头文件中声明析构函数/构造函数,并在cpp文件中执行
my_ClassA::my_ClassA()=default;


现在,您的
my_ClassC
有一个类型为
my_ClassB
的成员变量。在这种情况下,您必须
#包括“my_ClassB.h”
my_ClassC.h
头文件中的
,因为
my_ClassC
需要定义
my_ClassB
。但在大多数情况下,要么转发声明就足够了,要么稍加修改(例如,将值参数更改为引用参数)足够好,您不必交叉包含头文件。

没有足够的时间来给出正确的答案,但问题可能是相互包含(例如,a.h包括B.h,反之亦然)。只需手动查看包含指令的结果。您可以通过在B.h中仅使用一个类(例如a)来解决此问题,B.h中的时尚
类A;
的“正向声明”就足够了,没有标题。如果B.h中没有代码访问A的成员或创建对象,而只使用指针或引用,例如作为函数参数或成员(因为指针和引用的代码可以在不知道类的实现的情况下生成),则会出现这种情况.
我尝试在main.cpp中使用每个类的getter。但是我的一些类具有较大的向量、集合等,因此我不想一次又一次地复制它们。
只使用getter,它返回常量引用或非常量referenct@George我在第二行中陈述了一个错误。检查它。现在我已经突出显示了它。在我这是正常的文本。友谊是完全不相关的-你的类之间有一个循环依赖,你需要打破这种依赖。阅读关于转发声明(和关于引用)在你最喜欢的C++书籍中,@ MyBDNILO是的,我认为这主要是因为循环依赖性。我已经知道了前面的声明和引用。BTW我不确定的是,我们可以使用返回数据成员引用的GETSter。例如,通常当我使用普通函数时,返回一个对本地VA的引用。riable是UB。那么从getter返回对数据成员的引用是可以的还是不好的做法呢?公平点说。它确实减少了一点封装(可能只有公开const ref才是最好的)但我认为这是值得的。然而,这并不能真正解决op的问题。这是一个有效的近似值,但在这种情况下,有落入“上帝对象”的危险“反模式作为
状态的一种
实现是将所有类的数据收集到一个对象中是的,我做了几乎相同的事情,只是没有创建额外的文件(头)正如你所建议的。相反,我在任何需要的地方都有转发声明。在任何需要的地方都有头。程序按预期工作。我也有
#pragma once 
#include<string>
#include <vector>

//these three includes are for friend function BUT result in error incomplete type
#include "my_ClassB.h"
#include "my_ClassC.h"
#include "my_ClassD.h"
/////////////////////////////////////////////
namespace my_namespace{
    class my_ClassA{
        friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
            
        
        private:
        std::string name;  
        std::vector<std::string> vec;
        public:
            // use this getter to modify inner data by reference 
            std::vector<std::string>& get_vec();

            // use this getter to access data by const referenct
            std::vector<std::string> const & get_vec() const;

    };
    void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
    
}
#include "my_ClassA.h"

std::vector<std::string>& my_namespace::my_ClassA::get_vec() {
    return vec;
}


std::vector<std::string> const & my_namespace::my_ClassA::get_vec() const {
    return vec;
}
// class or struct which contains intermediate state
State state;
runComputation1(&state);
runComputation2(&state);
runComputation3(&state);
runComputation4(&state);
// my_forwards.h
namespace my_namespace {
  class my_ClassA;
  class my_ClassB;
  class my_ClassC;
  class my_ClassD;
  void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
}

// my_ClassA.h
#pragma once
#include<string>
#include <vector>
#include "my_forwards.h"
namespace my_namespace{
  class my_ClassA{
    friend void runComputation(my_ClassA&,my_ClassB&,my_ClassC&,my_ClassD&);
    
    private:
      std::string name;  
      std::vector<std::string> vec;
    public:
      std::vector<std::string> get_vec();
    };
}

// my_ClassA.cpp
#include "my_ClassA.h"
// include other my_ClassX here if needed, after my_ClassA.h

// implementation of my_ClassA:
std::vector<std::string> my_namespace::my_Class::get_vec() {
  return vec;
}