如何在C++中将一个对象保存在另一个对象中

ckocjqey  于 2023-02-06  发布在  其他
关注(0)|答案(2)|浏览(131)

我有两个班,A班和B班,

class A {

public: 
    A(B b);
    B GetB();

private:
    B b;
};

class B {

public:
    B();
    void IncrementCounter();
    int GetCounter();

private:
   int counter = 0;
};

我想把类型B的对象传递给类A的构造函数,然后把类B的示例保存在类A示例中,把类B示例作为参数传递的最好方法是什么,把类B示例保存在类A示例中的最好方法是什么。
注意:我不想创建类B示例的副本,我希望A.getB().GetCounter始终与b.GetCounter()相同。

int main(){
   B b;
   A a(b);
   b.IncrementCounter();
   a.getB().IncrementCounter();

   // then b.GetCounter() is same as a.getB().GetCounter() and both = 2

}

我看到人们使用指针/智能指针和引用/std:reference_wrapper,有什么区别?

nukf8bse

nukf8bse1#

如果不需要副本,请使用std::shared_ptr,例如:我假设您熟悉引用、常量引用和常量成员函数。

#include <memory>
#include <iostream>

class B
{
public:
    B()
    {
        number_of_instances++; // keep track of number of instances of class B
    }

    void IncrementCounter()
    {
        counter++;
    }

    int GetCounter() const
    {
        return counter;
    }

    int NumberOfInstances() const
    {
        return number_of_instances;
    }

private:
    int counter{ 0 };
    static int number_of_instances;
};

class A 
{
public:
    A(const std::shared_ptr<B>& b) :
        m_b{ b }
    {
    }
    
    // return a reference to the object shared_ptr m_b points to
    B& GetB() 
    {
        return *m_b;
    }

    // return a const reference to the object shared_ptr m_b points to
    const B& GetB() const
    {
        return *m_b;
    }

private:
    // https://en.cppreference.com/w/cpp/memory/shared_ptr
    std::shared_ptr<B> m_b;
};

int B::number_of_instances{ 0 };

int main()
{
    auto b = std::make_shared<B>();
    b->IncrementCounter();

    A a1(b);
    A a2(b);

    std::cout << "number of instances of B = " <<b->NumberOfInstances() << "\n";
    std::cout << "shared_ptr<B> reference count = " << b.use_count() << "\n";

    std::cout << a1.GetB().GetCounter();

    return 0;
}
dzjeubhm

dzjeubhm2#

注意:我不想创建类B示例的副本,我希望A.getB().GetCounter()总是与b.GetCounter()相同。
然后,您需要让A存储B&引用,而不是B对象示例,例如:

class A {
public: 
    A(B& b);
    B& GetB();

private:
    B& b;
};
A::A(B& b) : b(b) {
}

B& A::GetB() {
    return b;
}

只要B对象比A对象活得长(在您的示例中确实如此),就不会有问题,不需要(共享)指针。
但是,由于您在B之前声明了A,因此您根本无法在A中使用B,因为编译器在解析A时不知道B是什么。
由于B不依赖于A,因此您可以简单地交换它们声明的顺序,例如:

class B {
public:
    B();
    void IncrementCounter();
    int GetCounter();

private:
   int counter = 0;
};

class A {
public: 
    A(B& b);
    B& GetB();

private:
    B& b;
};

否则,如果您的情况不适合这样做,则必须在声明A之前使用B的前向声明,例如:

class B; // <--

class A {
public: 
    A(B& b);
    B& GetB();

private:
    B& b;
};

class B {
public:
    B();
    void IncrementCounter();
    int GetCounter();

private:
   int counter = 0;
};

前向声明仅在处理引用和指针时有效,而在处理示例时无效。

相关问题