简体   繁体   English

如何从在其中创建的不同类对象中访问类对象的成员函数?

[英]How do you access member functions of a class object from within a different class object that has been created in it?

class Class1  //Would be object mClass1
{
public:
 void Function1()
 {
  a++;
 }
private:
 int a = 0;
 Class2 mClass2;
}

(Editing in a space here to clarify Class2 is not defined after Class1; they are in separate files.) (在此处的空白处进行编辑以澄清 Class2 未在 Class1 之后定义;它们位于单独的文件中。)

class Class2  //Would be object mClass2
{
public:
 Function2()
 {
  Function1();  // Would be from mClass1
 }
}

So Class1 creates an instance of a Class2 object, and that Class2 object has a member function that wants to access the "parent" object's member function, without using inheritance.所以 Class1 创建了一个 Class2 对象的实例,并且 Class2 对象有一个成员函数,它想要访问“父”对象的成员函数,而不使用继承。

I don't know what I specifically need to search for to learn about this.我不知道我特别需要搜索什么来了解这一点。 Does it have to do with dereferencing a new pointer?它与取消引用new指针有关吗? Constructor type/initialization?构造函数类型/初始化? Does it have a terminology?它有术语吗? "Nested classes" bring up classes defined inside another class, which is not what this is. “嵌套类”调出在另一个类中定义的类,这不是这个类。

Without inheritance there is no way to get the 'parent class'.没有继承就无法获得“父类”。 So instead you should just pass the function as a parameter, maybe in the constructor of class 2 if you use it multiple times.因此,您应该将函数作为参数传递,如果您多次使用它,也许可以在类 2 的构造函数中传递它。 See for example: https://www.cprogramming.com/tutorial/function-pointers.html参见例如: https : //www.cprogramming.com/tutorial/function-pointers.html

You cannot do this.你不可以做这个。 Class2 is not known yet when you define Class1 , so the Class1::mClass2 data member cannot possibly be created.当您定义Class1Class2还不知道,因此不可能创建Class1::mClass2数据成员。 But this problem can be solved by defining Class2 before Class1 , and implementing Class2::Function2() outside the class and only after Class1 .但是这个问题可以通过在Class1之前定义Class2 ,并在类之外并且只在Class1之后实现Class2::Function2()来解决。

As for calling Function1() inside Function2() , Class2 needs to know the object on which to call Function1() .至于调用Function1()内部Function2() Class2需要知道该对象调用Function1() You could use a reference member for that that you initialize in the constructor:您可以使用在构造函数中初始化的引用成员:

// Forward-declaration of Class1 so that Class2 will be able to define
// references or pointers to Class1.
class Class1;

class Class2
{
public:
    // Constructor that requires a reference to our parent object.
    explicit Class2(Class1& parent)
        : parent_(parent)
    { }
    
    // Just declare the function. We need to implement it later, outside
    // this class definition because Class1 is not fully known yet and as
    // a result we can't have calls to Function1() because the compiler
    // doesn't know that function yet.
    void Function2();
    
private:
    // This is just a reference, so it works even if Class1 is not fully
    // known yet.
    Class1& parent_;
};

class Class1
{
public:
    void Function1() { /* ... */ }

private:
    int a = 0;
    Class2 mClass2{*this}; // Pass ourself as the parent object.
};

// Class1 is fully known now, so we can do calls to Function1().
inline void Class2::Function2()
{
    parent_.Function1();
}

This will work, but it has an important implication: it disables the assignment operator of Class2 .这会起作用,但它有一个重要的含义:它禁用了Class2的赋值运算符。 This is probably what you want in this case, because two copies of Class2 should probably not have the same Class1 parent object.在这种情况下,这可能是您想要的,因为Class2两个副本可能不应该具有相同的Class1父对象。

However, I don't see why you need to do this.但是,我不明白您为什么需要这样做。 It complicates matters for no good reason.它无缘无故地使事情复杂化。 Why not simply pass the Class1 object that Function2() should use as a function argument instead?为什么不简单地传递Function2()应该用作函数参数的Class1对象呢? So:所以:

class Class1;

class Class2
{
public:
    void Function2(Class1& c1_obj);
};

class Class1
{
public:
    void Function1() { /* ... */ }

private:
    int a = 0;
    Class2 mClass2;
};

inline void Class2::Function2(Class1& c1_obj)
{
    c1_obj.Function1();
}

So whenever Class1 needs to call Class2::Function2() , just pass *this to it.因此,每当Class1需要调用Class2::Function2() ,只需将*this传递给它。 It's simpler and doesn't have the drawbacks of holding a reference or pointer to another object.它更简单,并且没有持有指向另一个对象的引用或指针的缺点。

With canonic classes - no way to do this, because Class2 is incomplete within Class1 and if you declare Class2 inside of Class1 (as a nested class), it wouldn't have access to Class1 , because Class1 incomplete!随着法服类-没有办法做到这一点,因为Class2是不完整的内Class1 ,如果你申报Class2Class1 (作为嵌套类),那就无法获得Class1 ,因为Class1不完整!

Looks like an unsolvable paradox?看起来像一个无法解决的悖论? It is unsolvable in OOP land, but can be dodged just like Nikos had shown.它在 OOP 领域无法解决,但可以像 Nikos 展示的那样躲避。 But the problem of undefined types in some cases can be resolved in C++ or similar concept-oriented languages by using CRTP - Curiously recurring template .但是在某些情况下未定义类型的问题可以在 C++ 或类似的面向概念的语言中通过使用 CRTP- Curiously recurring template 来解决

If it is possible or not in your use-case and how complex it would be depending on what purpose you pursue.在您的用例中是否可能,以及它的复杂程度取决于您追求的目的。 Here is an example of a paradoxical CRTP behavior - a member of base class is able to call a member of derived class:这是一个矛盾的 CRTP 行为的例子 - 基类的成员能够调用派生类的成员:

#include <iostream>

template < class T>
class Base { 

public:
      template <class U>
      struct Accessor : public U {
           static void evoke_foo( T& obj)
           {
                 return  (obj.*(static_cast< void(T::*)() >(&Accessor::foo))) ();
           }
      };

      void evoke(  )
      {  
           Accessor<T>::evoke_foo( *static_cast<T*>(this) );
      }
};


class Derived : public Base<Derived> {
protected:
      void foo()  { std::cout << "Foo is called" << std::endl; }
};


int main()
{
    Derived a;
    a.evoke();   // evoke belongs to base.
}

Now if we'd want to determine return type of foo() automatically here, this would become an insanely complex piece of code.现在如果我们想在这里自动确定foo()返回类型,这将成为一段非常复杂的代码。 Some problems like that are solved in implementations of standard namesake of evoke method.一些类似的问题在evoke方法的标准同名实现中得到解决。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 您如何设计具有一个成员是基类的对象? - How do you design an object that has a member which is a base class? 多态性:如何访问派生类成员函数? - Polymorphism: How do you access derived class member functions? 如何从 class 访问另一个成员 class object - How to acess another member class object from within class 如何迭代每个对象并从c ++中的coustom类数组访问其成员函数? - How to iterate each object and access its member functions from array of coustom class in c++? 如何调用一个类函数,但使用另一个类对象 - How do you call a class function but with a different class object 如何访问 object(也是该类的成员)中的 class 成员变量 - How to access a class member variable in an object (which is also a member of the class) 使用类实例和成员函数时,如何操作主程序中数组内的值? - How do you manipulate the values inside arrays within the main program when using class instances and member functions? 从同一类中的另一个成员对象访问成员对象 - Accessing member objects from another member object within the same class 将类的成员存储为没有此类方法的父类的对象时,如何访问该类的成员? - How to access a member of a class when it is stored as a object of a parent class that has no such method? c ++和OpenGl:如何从类中创建网格对象实例 - c++ & OpenGl: How do you create a mesh object instance from within a class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM