相同类的C ++实例 [英] C++ instance of same class

查看:81
本文介绍了相同类的C ++实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道在C ++中是否可以像在Java中一样做同样的事情。
这意味着:

 公共类A {
私有A a1;
私人A a2;

A getA1(){
return a1;
}

getA2(){
return a2;
}

setA1(A a1){
this.a1 = a1;
}

setA2(A a2){
this.a2 = a2;
}
}

现在我想要在C ++中使用相同的东西或解决方法。

解决方案

是的,它在C ++中是可行的。但是语法会有所不同:


  1. this-> 而不是此。



  2. private: / public:,而不是每个成员 private / public



  3. 记住在课程结束时有;



  4. A * 作为成员(或 std :: uniqe_ptr< A> std :: shared_ptr< A> std :: weak_ptr< A> )。






项目1-3只是语法。第4项是Java和C ++之间的本质区别:



  • 在Java中,对象变量是对对象的引用而在C ++中,对象变量是一个值。这就是为什么您不能在C ++中拥有自己的直接成员,原因是对象的大小将是无限的 (A的实际值是A,实际的值是A (递归)。


    在Java中,当A持有A时,它只是持有对另一个A >(是的,您仍然可以递归访问引用的A,但它不是您大小的一部分,您只需保存对其的引用,它就会存储在内存中的其他位置。大小的增加只是引用的大小)


    通过添加引用变量或指针实现类似的语义。 >& 作为参考,或 * 作为指针:

      A& a2 = a1; // a2是对A的引用,并分配有对a1 
    的引用// //注意,上面的a1也被假定为A&类型。

    A * a2 = a1; // a2是指向A的指针,并分配有存储在a1
    中的地址// //注意上面的a1也被假定为A *


  • Java垃圾收集器回收未使用的内存,而在C ++中,程序员需要处理这些内存,可能需要使用智能指针之类的C ++工具



  • Java垃圾收集器通过可达性跟踪,C ++智能指针基于作用域生存期。此外,C ++ shared_ptr 基于引用计数有其优点,但受参考周期的限制,可能会发生内存泄漏,应通过适当设计代码来避免。






抱住自己 的C ++版本可能看起来像下面的任何一种(或它们的变体),具体取决于实际需要:


选项1-A是持有,但不拥有 a1和a2


  A类{
A * a1 = nullptr;
A * a2 = nullptr;

public:
A * getA1(){
return a1;
}

A * getA2(){
return a2;
}

setA1(A * a1){
this-> a1 = a1;
}

void setA2(A * a2){
this-> a2 = a2;
}
};


选项2-A是拥有 a1和a2作为唯一资源


  A类{
std :: unique_ptr< A> a1 = nullptr;
std :: unique_ptr< A> a2 = nullptr;

public:
A * getA1(){
return a1.get();
}

A * getA2(){
return a2.get();
}

void setA1(std :: unique_ptr< A> a1){
this-> a1 = std :: move(a1);
}

void setA2(std :: unique_ptr< A> a2){
this-> a2 = std :: move(a2);
}
};


选项3-A是持有 a1和a2作为共享资源 *


* 需要确保避免循环所有权泄漏。

  A类{
std :: shared_ptr< A> a1 = nullptr;
std :: shared_ptr< A> a2 = nullptr;

public:
自动getA1(){
return a1;
}

auto getA2(){
return a2;
}

void setA1(std :: shared_ptr< A> a1){
this-> a1 = a1;
}

void setA2(std :: shared_ptr< A> a2){
this-> a2 = a2;
}
};


选项4-A 持有指向a1和a2 *的弱指针 sup>


* 在可能的情况下, std :: weak_ptr 选项是相关的

  class A {
std :: weak_ptr< ; A> a1 = nullptr;
std :: weak_ptr< A> a2 = nullptr;

公共:
std :: shared_ptr< A> getA1(){
return a1.lock();
}

std :: shared_ptr< A> getA2(){
return a2.lock();
}

void setA1(std :: shared_ptr< A> a1){
this-> a1 = a1;
}

void setA2(std :: shared_ptr< A> a2){
this-> a2 = a2;
}
};

选项4代码示例: http://coliru.stacked-crooked.com/a/92d6004280fdc147




请注意,使用 A& (引用A)作为成员不是一种选择,因为在C ++中,参考变量比天主教婚礼更强大,它们是为了变量的生存期,而无需重新分配给另一个引用。


但是,如果 a1 a2 是在对象诞生时就知道的,在对象的生命周期内永不改变并保持活动,那么以下选项也是可能的:


选项5-A是持有对a1和a2的引用 *


* 仅当可以在创建时设置对 a1 a2 的引用,永不更改,并且在对象生命周期内保持有效。

  A类{
A& a1;
A& a2;

公共:
A(A& a1,A& a2):a1(a1),a2(a2){}

A& getA1(){
返回a1;
}

A& getA2(){
返回a2;
}
};


I wondered whether it is possible in C++ to do the same stuff like in Java. That means something like this:

public class A {
  private A a1;
  private A a2;
  
  A getA1(){
   return a1;
  }

  A getA2(){
   return a2;
  }

  void setA1(A a1){
   this.a1 = a1;
  }

  void setA2(A a2){
   this.a2 = a2;
  }
}

Now I want the same thing or a workaround in C++.

解决方案

Yes, it's doable in C++. But the syntax would be a little different:

  1. this-> instead of this.

  2. private:/public: instead of private/public per member

  3. remember to have ; at the end of the class

  4. A* as member (or std::uniqe_ptr<A> or std::shared_ptr<A> or std::weak_ptr<A>).


Items 1-3 are merely syntax. Item 4 is an essential difference between Java and C++:

  • In Java an object variable is a reference to the object while in C++ an object variable is a value. This is why you can't hold in C++ a direct member of yourself, as is, the size of the object would be infinite (A holding an actual value of A, holding an actual value of A, ... recursively).

    In Java when A holds an A, it just holds a reference to the other A (yes, you can still access recursively the referenced A, but it is not part of your size, you just hold a reference to it, it is stored elsewhere in memory. The addition to your size is just the size of a reference).

    You can achieve similar semantics in C++ with reference variables or pointers, by adding & for a reference or * for a pointer:

    A& a2 = a1; // a2 is a reference to A, assigned with a reference to a1
                // note that a1 above is assumed to be also of type A&
    
    A* a2 = a1; // a2 is a pointer to A, assigned with the address stored in a1
                // note that a1 above is assumed to be also of type A*
    

  • Java Garbage Collector reclaims unused memory while in C++ the programmer needs to handle that, possibly with C++ tools such as smart pointers.

  • Java Garbage Collector reclaims unused memory via Trace by Reachability, C++ smart pointers are based on scope lifetime. Additionally, C++ shared_ptr is based on reference counting which has its advantages, but is subject to reference cycles possible leak of memory, which should be avoided with proper design of your code.


The C++ version of "holding myself" may look like any of the below (or variations of them), depending on the exact need:

Option 1 - A is holding but not owning a1 and a2

class A {
   A* a1 = nullptr;
   A* a2 = nullptr;

public: 
   A* getA1(){
      return a1;
   }

   A* getA2(){
     return a2;
   }

   void setA1(A* a1){
     this->a1 = a1;
   }

   void setA2(A* a2){
     this->a2 = a2;
   }
};

Option 2 - A is owning a1 and a2 as a unique resource

class A {
   std::unique_ptr<A> a1 = nullptr;
   std::unique_ptr<A> a2 = nullptr;

public: 
   A* getA1(){
      return a1.get();
   }

   A* getA2(){
     return a2.get();
   }

   void setA1(std::unique_ptr<A> a1){
     this->a1 = std::move(a1);
   }

   void setA2(std::unique_ptr<A> a2){
     this->a2 = std::move(a2);
   }
};

Option 3 - A is holding a1 and a2 as a shared resource*

* need to make sure you avoid cyclic ownership leak.

class A {
   std::shared_ptr<A> a1 = nullptr;
   std::shared_ptr<A> a2 = nullptr;

public: 
   auto getA1(){
      return a1;
   }

   auto getA2(){
     return a2;
   }

   void setA1(std::shared_ptr<A> a1){
     this->a1 = a1;
   }

   void setA2(std::shared_ptr<A> a2){
     this->a2 = a2;
   }
};

Option 4 - A is holding weak pointers to a1 and a2*

* the option of std::weak_ptr is relevant in case of possible cyclic dependency, a1 and a2 are owned elsewhere and might not be alive.

class A {
   std::weak_ptr<A> a1 = nullptr;
   std::weak_ptr<A> a2 = nullptr;

public: 
   std::shared_ptr<A> getA1(){
      return a1.lock();
   }

   std::shared_ptr<A> getA2(){
     return a2.lock();
   }

   void setA1(std::shared_ptr<A> a1){
     this->a1 = a1;
   }

   void setA2(std::shared_ptr<A> a2){
     this->a2 = a2;
   }
};

Option 4 code example: http://coliru.stacked-crooked.com/a/92d6004280fdc147


Note that using A& (reference to A) as a member, is not an option, as in C++ reference variables are stronger than Catholic wedding, they're for the lifetime of the variable without any way to reassign to another reference. And they must be assigned to a valid reference when born.

However, if a1 and a2 are known when the object is born, never change and stay alive for the duration of the object's lifetime, then the following option is also possible:

Option 5 - A is holding references to a1 and a2*

* this option is relevant only if the reference to a1 and a2 can be set upon creation, never changes and stays alive for the duration of the object's lifetime.

class A {
   A& a1;
   A& a2;

public:
   A(A& a1, A& a2): a1(a1), a2(a2) {}

   A& getA1(){
      return a1;
   }

   A& getA2(){
      return a2;
   }
};

这篇关于相同类的C ++实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆