C++ C++;通过函数初始化类指针

C++ C++;通过函数初始化类指针,c++,class,pointers,C++,Class,Pointers,我有一个程序,它有一个类class a的单个实例和多个类class B的实例,其中class B的每个实例都有一个指向class a的单个实例的指针。我想我可以在main()中启动它们,然后将class A的单个实例的地址传递给class B的所有实例。我想知道这是否正确,我一直在研究继承,但根据我的理解(这通常是错误的),如果您继承另一个类,那么该类每次都会被初始化,因此创建了多对多关系,而我想要一对多关系。我附上了一些代码。如有任何建议,将不胜感激 // C/C++ standard lib

我有一个程序,它有一个类
class a
的单个实例和多个类
class B
的实例,其中
class B
的每个实例都有一个指向
class a
的单个实例的指针。我想我可以在
main()
中启动它们,然后将
class A
的单个实例的地址传递给
class B
的所有实例。我想知道这是否正确,我一直在研究继承,但根据我的理解(这通常是错误的),如果您继承另一个类,那么该类每次都会被初始化,因此创建了多对多关系,而我想要一对多关系。我附上了一些代码。如有任何建议,将不胜感激

// C/C++ standard library
#include <vector>
#include <iostream>
#include <cstdlib>

using namespace std;

class A {
public:
    double get_value(void) {
        return value;
    }
private:
    double value;
};


// Forward declare A if split over files
class B {
public:
    void assign_pointer(A class_a_to_assign) {
        class_a = &class_a_to_assign; // assign the pointer the address to point to
    }
    void update_my_value(void) {
        value_b += class_a->get_value();
    }

    double get_value(void) {
        return value_b;
    }
private:
    double value_b = 0.1;
    A* class_a; // pointer to class A
};

int main() {
    cout << "hello world" << endl;
    // create 2 instances of B there could be thousands of these tho.
    B b1;
    B b2;
    // create 1 instance of A
    A a1;

    // Now I want both instances of the B class to point to the one instance of A
    b1.assign_pointer(a1);
    b2.assign_pointer(a1);

    // THen do stuff with B so that if any changes occur in A, then they can be automatically updated in class B through the pointer

    b1.update_my_value();
    b2.update_my_value();

    cout << b1.get_value() << " and " << b2.get_value() << endl;
    return 0;
}
//C/C++标准库
#包括
#包括
#包括
使用名称空间std;
甲级{
公众:
双get_值(void){
返回值;
}
私人:
双重价值;
};
//如果在文件上拆分,则向前声明
B类{
公众:
void assign_指针(类_A_to_assign){
class_a=&class_a_to_assign;//将要指向的地址分配给指针
}
无效更新我的值(无效){
值_b+=类_a->获取值();
}
双get_值(void){
返回值_b;
}
私人:
双值_b=0.1;
A*class_A;//指向类A的指针
};
int main(){

cout下面的函数违反了您仅创建一个
A
实例并使用指向该
A
实例的指针的意图

void assign_pointer(A class_a_to_assign) {
    class_a = &class_a_to_assign; // assign the pointer the address to point to
}
由于您接受的是按值分配的
类,因此存在两个问题:

  • 每次调用函数时,都会创建一个新的
    a
    实例
  • 您正在存储指向临时对象的指针。一旦函数返回,指针将变为无效指针
  • 通过将参数设置为引用类型,可以解决这两个问题

    void assign_pointer(A& class_a_to_assign) {
        class_a = &class_a_to_assign; // assign the pointer the address to point to
    }
    

    此外,正如在注释中提到的,最好在
    B
    对象之前创建
    A
    对象,因为您希望
    A
    B
    对象更长寿

    int main() {
        cout << "hello world" << endl;
    
        // create 1 instance of A
        A a1;
    
        // create 2 instances of B there could be thousands of these tho.
        B b1;
        B b2;
    
        ...
    }
    
    intmain(){
    
    cout您所描述的内容听起来很像。处理这种情况的一种方法是让singleton类包含一个
    静态
    方法,该方法返回类的单个实例。因此它看起来像这样:

    class A {
        public:
            A() { /* constructor */ }
            ~A() { /* destructor */ }
            static A* getInstance();
            double get_value(void) {
                return value;
            }
        private:
            double value;
    }; 
    
    static A gSharedInstance;
    
    static A* A::getInstance()
    {
        return &gSharedInstance;
    }
    
    static
    方法将位于实现(.cpp)文件中,如下所示:

    class A {
        public:
            A() { /* constructor */ }
            ~A() { /* destructor */ }
            static A* getInstance();
            double get_value(void) {
                return value;
            }
        private:
            double value;
    }; 
    
    static A gSharedInstance;
    
    static A* A::getInstance()
    {
        return &gSharedInstance;
    }
    
    这将在静态初始化时构造一个
    A
    ,当调用上述方法时,它将返回指向该静态共享实例的指针。现在,无论您想在何处使用
    A
    ,您只需执行以下操作:

    A* sharedA = A::getInstance();
    double value = sharedA->getValue(); // Or whatever you need from it.
    

    请注意,singleton本质上是一个全局变量,全局变量有一些问题(例如,在本例中,它的
    成员集在哪里?),但如果类表示某种真正唯一的资源(例如,设备上唯一的麦克风),则,那么就值得使用一个单例来表示它。在这种情况下,最好将其设置为只读,这样就不能在许多不同的地方设置其状态。另外,请注意,您可能需要添加代码来处理同时访问它的多个线程。

    首先,您的代码中存在一个严重问题:

    void assign_pointer(A class_a_to_assign) {
        class_a = &class_a_to_assign; // assign the pointer the address to point to
    }
    
    这里,
    class\u a\u to\u assign
    是一个按值函数参数,它在生存期方面与任何函数局部变量大致相同。换句话说,一旦控件离开方法的作用域,
    class\u a
    就成为一个悬空指针(指向不再存在的局部对象的指针)。快速修复程序简单明了:

    void assign_pointer(A &class_a_to_assign) {
        class_a = &class_a_to_assign; // assign the pointer the address to point to
    }
    
    区别只是一个字符——函数参数声明中的符号将其从临时值转换为对更长寿命对象的引用

    接下来,如果您有一个
    类a
    的单个对象,您是否考虑过将其设置为单例对象?这样,
    B
    的实例甚至不需要保留该指针,
    a
    本身管理该实例。关于设计单例类,有很多说法,一个粗糙而幼稚的实现类似于:

    class A {
        A(); // note it's private
    public:
        int getValue() const;
        static A &instance() {
            static A retVal;
            return A;
        };
    };
    
    class B {
    public:
        void update_my_value(void) {
            value_b += A::instance().get_value();
        }
    };
    
    int main() {
        A::instance(); // to warmup the static instance before any users are created
        B b1; // no assign_pointer is needed as A is a Singleton
        B b2; // and every B always knows where to find it
    }
    

    一个改进是在所有
    B
    对象之前创建
    a1
    ,以确保它比它们更长寿,因为它们依赖于它。继承不是多对多的,它只是每个对象的一对一关系。(另外,
    a
    的转发声明不足以满足
    B
    的定义,您的示例读取未初始化的
    a::value
    )这里没有其他(明显)错误(即使可以进行重大改进)--这就是你的全部问题吗?另一个问题:确保
    B
    只能通过在构造函数中执行
    explicit B(A*A):class_A(A){
    来从
    A*
    实例化。