Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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++ 使用另一个std:vector访问类中std:vector的std:vector的类成员_C++_Stdvector - Fatal编程技术网

C++ 使用另一个std:vector访问类中std:vector的std:vector的类成员

C++ 使用另一个std:vector访问类中std:vector的std:vector的类成员,c++,stdvector,C++,Stdvector,我对如何使用另一个std::vector访问类中的std::vector感到困惑。前面的讨论()涉及类似的问题,但似乎我一定是误解了什么 下面是我的代码的草图: class Employee m_id; public: set_id(int id); id(); In Employee.cpp void Employee::set_id(const int id) { m_id = id; // m_id is 5 } int Employe

我对如何使用另一个std::vector访问类中的std::vector感到困惑。前面的讨论()涉及类似的问题,但似乎我一定是误解了什么

下面是我的代码的草图:

class Employee
    m_id;
public:
    set_id(int id);
    id();

In Employee.cpp
void Employee::set_id(const int id)
{
    m_id = id;          // m_id is 5
}

int Employee::id() const
{
    return m_id;        // m_id is rubbish
}

class Company
public:
    std::vector<Employee> m_employees;

In Company.cpp
void Company::addEmployee(const addEmployee employee) // A vant to pass a copy of employee
{
    m_employees.push_back(employee);
}
std::vector<Employee> Company::employees()
{
    return m_employees;
}

in myClass.h
std::vector<Company> m_companies;

in myClass.cpp  

int empl_id = 5;   // test value
m_companyIndex = 0;   // for test
m_emplIndex = 0;   // 

Company company; 
Employee employee;
m_companies.push_back(company);
m_companies.at(m_companyIndex).addEmployee(employee);

            m_companies.at(m_companyIndex).employees().at(m_emplIndex).set_id(empl_id);
int idRet = m_companies.at(m_companyIndex).employees().at(m_emplIndex).id(); 

idRet contans an apparently random number, instead of 5. Using a debugger shos that 
class员工
m_id;
公众:
设置_id(int id);
id();
在Employee.cpp中
void Employee::set_id(const int id)
{
m_id=id;//m_id是5
}
int Employee::id()常量
{
返回m_id;//m_id是垃圾
}
阶级公司
公众:
std::vector m_员工;
In Company.cpp
作废公司::addEmployee(const addEmployee employee)//传递员工副本的vant
{
m_员工。推回(员工);
}
std::vector公司::员工()
{
返回m_员工;
}
在我的班级里
标准:向量m_公司;
在myClass.cpp中
int emp_id=5;//测试值
m_companyIndex=0;//测试
m_emplIndex=0;//
公司;
员工;
m_公司。推回(公司);
m_companys.at(m_companyIndex).addEmployee(雇员);
m_companys.at(m_companyIndex.employees().at(m_employindex.set_id(employid));
int idRet=m_company.at(m_companyIndex.employees().at(m_employindex.id();
idRet包含一个明显的随机数,而不是5。使用调试器可以

如果我在myClass中实例化Employee,我可以设置并读回m_id;我是公司的,所以这个问题似乎与std::vector m_员工有关;同班同学。这可能与“回报值优化”有关吗?顺便说一下,我使用的是gcc 7.5.4

正如@dxiv所指出的,您的Company::employees函数构造并返回m_employees列表的副本。因此,您的代码

m_companies.at(m_companyIndex).employees().at(m_emplIndex).set_id(empl_id);
翻译为:

Get the element of m_companies at the index m_companyIndex,
then construct a copy of its m_employees list,
then get the element of that copy at index m_emplIndex,
then set the id of that element to empl_id,
and then destroy the copy.
当然,这根本不会改变m_员工列表的内容

通过使Company::employees返回对雇员列表的非常量引用,而不是副本,可以使代码或多或少正确地工作。但是,这样的函数不能在“const”公司对象上调用,因此您可能还需要一个返回const引用的“const”版本的函数

但是,即使通过非常量引用公开类的私有实现细节,例如m_employees,也是危险的,因为如果外部代码使用此引用修改m_employees向量,则不会通知employees类,并且它拥有的任何其他内部数据(可能取决于m_employees vector的内容)不能同时更新

因此,通常情况下,外部代码最好要求包含类(Employees)进行更改,而不是要求包含类返回可由外部代码用于进行更改的非常量引用。这样,Employees类可以进行更改,还可以更新它拥有的任何其他内部数据,这些数据可能取决于m_Employees内容

例如,您可以添加一个Employees::at函数,该函数返回对元素的引用,以便将上述代码行重写为:

m_companies.at(m_companyIndex).at(m_emplIndex).set_id(empl_id);
或者更好:

m_companies.at(m_companyIndex).set_id(m_emplIndex, empl_id);
或者更好,如果m_companys包含在名为“companys”的companys对象中:

companies.set_id(m_companyIndex, m_emplIndex, empl_id);
使用这些函数,您可以将Employees::m_Employees更改为使用完全不同的数据结构(例如,排序列表、链表或集合),而不会影响您的界面。这减少了外部代码和类内部代码之间的耦合,并使将来需要更改时更容易更改


一般来说,在设计此类接口时,尤其是在对对象内容进行修改的接口方面考虑是明智的:许多对象在没有其知识的情况下,通过外部类改变其内部内容的反应不好,因此,最好在可能的情况下要求包含对象更改其子对象,而不是允许从类外部访问对它们的非常量引用。

正如@dxiv所指出的,您的Company::employees函数构造并返回一份m_employees列表。因此,您的代码

m_companies.at(m_companyIndex).employees().at(m_emplIndex).set_id(empl_id);
翻译为:

Get the element of m_companies at the index m_companyIndex,
then construct a copy of its m_employees list,
then get the element of that copy at index m_emplIndex,
then set the id of that element to empl_id,
and then destroy the copy.
当然,这根本不会改变m_员工列表的内容

通过使Company::employees返回对雇员列表的非常量引用,而不是副本,可以使代码或多或少正确地工作。但是,这样的函数不能在“const”公司对象上调用,因此您可能还需要一个返回const引用的“const”版本的函数

但是,即使通过非常量引用公开类的私有实现细节,例如m_employees,也是危险的,因为如果外部代码使用此引用修改m_employees向量,则不会通知employees类,并且它拥有的任何其他内部数据(可能取决于m_employees vector的内容)不能同时更新

因此,通常情况下,外部代码最好要求包含类(Employees)进行更改,而不是要求包含类返回可由外部代码用于进行更改的非常量引用。这样,Employees类可以进行更改,还可以更新它拥有的任何其他内部数据,这些数据可能取决于m_Employees内容

例如,您可以添加一个Employees::at函数,该函数返回对元素的引用,以便将上述代码行重写为:

m_companies.at(m_companyIndex).at(m_emplIndex).set_id(empl_id);
或者更好:

m_companies.at(m_companyIndex).set_id(m_emplIndex, empl_id);
或者更好,如果m_companys包含在名为“companys”的companys对象中:

companies.set_id(m_companyIndex, m_emplIndex, empl_id);
使用这些函数,您可以将Employees::m_Employees更改为使用完全不同的数据结构(例如,排序列表、链表或集合),而不会影响您的界面。这减少了外部代码和类内部代码之间的耦合,并使将来需要更改时更容易更改

总的来说,考虑一下是明智的