简体   繁体   English

我应该如何为我的班级写构造函数

[英]How should I write the constructor for my class

I have a container class to which i can send a Geometry object as constructor argument. 我有一个容器类,可以向其发送几何对象作为构造函数参数。

Geometry is a polymorphic class as interface for other geometric types like Sphere and Rectangle. 几何是一个多态类,可作为“球”和“矩形”等其他几何类型的接口。

My question is that in Container class the constructor with arguments "Container(std::string str, Geometry* geometry)" can i code this in more flexible manner. 我的问题是,在Container类中,带有参数“ Container(std :: string str,Geometry * geometry)”的构造函数可以以更灵活的方式对此进行编码。

Whenever i will add a new SubClass to Geometry than i would need to write another IF condtion in Container class Constructor. 每当我将一个新的SubClass添加到Geometry时,我就需要在Container类Constructor中编写另一个IF条件。

include "pch.h"
#include <iostream>
#include<fstream>
#include "Container.h"
#include "Geometry.h"
#include "Sphere.h"
#include "Rectangle.h"
#include "Container.h"

int main()
{
    const char* fileName = "saved.txt"; 
    Sphere sph;
    Rectangle rect;
    Container contSphere("ABC", &sph);
    Container contRectangle("DEF", &rect);
    Sphere* s = (Sphere*)contSphere.getGeomtry();
    s->PrintGeom();
    Rectangle* r = (Rectangle*)contRectangle.getGeomtry();
    r->PrintGeom(); 
    do
    {
        std::cout << '\n' << "Press a key to continue...";
    } while (std::cin.get() != '\n');
}

/////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////// /////////////////////////////////////////////

#pragma once
#include <string>
class Geometry
{
private:
    std::string stdstringGeom;
    std::string stdstrType;

public:

    Geometry() : stdstringGeom("GeometyrString"), stdstrType("Geometry") {}
    virtual ~Geometry() {}


    virtual std::string getType()
    {
        return stdstrType;
    }

     virtual void  PrintGeom()
    {
        std::cout << "geometry virtual function";
    }

};

///////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////// ///////////////////////////////

#pragma once

#include "Geometry.h"
class Sphere : public Geometry
{
private:
    std::string stdstrSphere;
    std::string stdstrType;


public:
    Sphere() : Geometry() ,  stdstrSphere( "DefaultSphere") , stdstrType("Sphere") {}
    Sphere( std::string str) : Geometry() ,  stdstrSphere(str) , stdstrType("Sphere"){}
    void PrintGeom()
    {
        std::cout << "Sphere Virtual Function" << std::endl;
    }

    std::string getType()
    {
        return stdstrType;
    }

};

///////////////// Defination for Constructor class//////////////////// /////////////////构造函数类的定义//////////////////////

#include "Geometry.h"
#include "Sphere.h"
#include "Rectangle.h"

class Container
{
private:
    std::string stdstrCont;
    Geometry* geom;

public:
    Container() : stdstrCont("NoName") { geom = new Geometry; }
    Container(std::string str, Geometry* geometry) : stdstrCont(str)
    {
    // I am doing this to avoid slicing and i want to do a deep copy.   
     if (geometry->getType() == "Sphere")
        {
            Sphere* sph = (Sphere*)geometry;
            geom = new Sphere(*sph);
        }
        else if (geometry->getType() == "Rectangle")
        {
            Rectangle* rec = (Rectangle*)geometry;
            geom = new Rectangle(*rec);

        }
    }

    ~Container()
    {
        if (geom != nullptr)
            delete geom;
    }

    Geometry* getGeomtry()
    {
        return geom;
    }

    void PrintContainer()
    {
        std::cout << stdstrCont;
    }
};

Your design is all backward, and a consequence is that you are making the Container responsible for working out the type of all Geometry objects passed to it, in order to copy them. 您的设计是全部落后的,结果是使Container负责计算传递给它的所有Geometry对象的类型,以便复制它们。 That will make your Container a maintenance nightmare - if someone creates another class derived from Geometry , they can forget to modify Container accordingly. 这将使您的Container成为维护的噩梦-如果有人创建了另一个从Geometry派生的类,他们可能会忘记相应地修改Container

You've also omitted code that is relevant to your question (like virtual destructors) and included code that is irrelevant to the question (declaration of std::string members, and initialisation of them in constructors, and other virtual functions). 您还省略了与您的问题相关的代码(例如虚拟析构函数),并包括了与该问题不相关的代码(声明std::string成员,并在构造函数和其他虚拟函数中对其进行了初始化)。

Instead, it would be better to make the class Geometry , and its derived classes, responsible for copying themselves. 相反,最好让类Geometry及其派生类负责复制自身。

At heart would be the Geometry class itself 本质上是Geometry类本身

 #include <memory>     // for std::unique_ptr
 class Geometry
 {
    public:
        Geometry() {};
        virtual ~Geometry() = default;

         virtual std::unique_ptr<Geometry> Clone() const = 0;
 };

(I've omitted the std::string members for convenience). (为方便起见,我省略了std::string成员)。 The derived classes then override the Clone() function, viz; 然后,派生的类将覆盖Clone()函数,即;

 class Sphere: public Geometry
 {
    public:
        Sphere() : Geometry() {};
         ~Sphere() = default;

         std::unique_ptr<Geometry> Clone() const {return std::unique_ptr<Geometry>(new Sphere(*this));}; 
 };

 // similarly for other shapes

The Clone() function is pure virtual in Geometry , so the derived classes cannot be instantiated unless you remember to override it. Clone()函数在Geometry是纯虚拟的,因此除非您记得重写它,否则无法实例化派生的类。

The responsibility for cloning rests with Geometry and its derived classes - and the compiler will helpfully diagnose an error if a class is derived from Geometry that does not override the Clone() function. 克隆的责任在于Geometry及其派生类-如果从Geometry派生的类没有覆盖Clone()函数,则编译器将有助于诊断错误。

Then, all a Container needs to do is have a member std::unique_ptr<Geometry> or (if you intend to have a set of them) a std::vector<std::unique_ptr<Geometry> > . 然后, Container所需要做的就是拥有一个成员std::unique_ptr<Geometry>或(如果您打算拥有一组成员)一个std::vector<std::unique_ptr<Geometry> > For the case where the Container only needs a single Geometry , the definition of Container might be 对于其中的情况下, Container只需要一个Geometry的定义中, Container可能是

 class Container
 {
       public:
            Container() : geom() {};
            Container(Geometry *p) : geom(p->Clone()) {};
            Container(const Container &c) : geom(c.geom->Clone()) {};
            Container &operator=(const Container &c)
            {
                  geom = c.geom->Clone();   // this will release the existing c.geom
                  return *this;
            };
            ~Container() = default;
       private:

             std::unique_ptr<Geometry> geom;
 };

The reason I've used std::unique_ptr<Geometry> in the above (instead of Geometry * as in your code) is that std::unique_ptr<> avoids the need to explicitly decide when to destroy a Geometry object. 我在上面使用std::unique_ptr<Geometry>的原因(而不是代码中的Geometry * )是因为std::unique_ptr<>无需明确决定何时销毁Geometry对象。

The no-argument constructor of Container initialises to containing a null Geometry (ie a null pointer). Container的无参数构造函数初始化为包含空Geometry (即空指针)。

The constructor of Container that accepts a Geometry * clones the passed object, and does not assume ownership of it. 接受Geometry *Container的构造函数将克隆所传递的对象,并且不承担该对象的所有权。 This means the caller is responsible for the lifetime of the object it passes. 这意味着调用方应对其传递的对象的生命周期负责。 This is consistent with your main() , which constructs objects of automatic storage duration. 这与main()一致,后者构造了自动存储持续时间的对象。

Note that I'm following the "rule of three" - if a non-default version of a copy constructor, copy assignment, or destructor is defined, then the other two should also be defined. 请注意,我遵循“三个规则”-如果定义了副本构造函数,副本分配或析构函数的非默认版本,则还应该定义另外两个。 The operator=() in the above works in a manner consistent with the copy constructor (ie it clones objects in the Container , rather than causing Geometry objects to be shared between Container s). 上面的operator=()以与复制构造函数一致的方式工作(即,它在Container克隆对象,而不是使Geometry对象在Container之间共享)。 The destructor is explicitly defined as the default, since the Container is not explicitly managing lifetime of its members (the destructor of std::unique_ptr does the work). 由于Container未显式管理其成员的生存期,因此将析构函数明确定义为默认值( std::unique_ptr的析构函数可以完成此工作)。

暂无
暂无

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

相关问题 在Singleton类的情况下我应该如何编写复制构造函数?如何重载=运算符? - How should I write a copy constructor in case of Singleton class and how should I overload = operator for same? 我应该如何为包含动态数组的 class 编写所需的构造函数? - How should i write needed constructor for class which includes dynamic array? 如何为具有std :: stringstream成员的类编写复制构造函数? - How do I write a copy constructor for my class which has a std::stringstream member? 如何编写构造函数 function 来设置向量的大小,该向量是 C++ 中的 class 的属性? - How do I write the constructor function that sets the size of a vector which is the attribute of my class in C++? 我应该如何编写一个复制构造函数来初始化另一个 object? - How should I write a copy constructor to initialise another object? 在该类中,我应该如何写以获得“ 2”作为输出? - How should I write to get '2' as output in this class? 我班级的建设者应该做多少工作? - How much work should constructor of my class perform? 我应该如何为矩阵类实现复制构造函数和赋值运算符? - How should I implement a copy constructor & assignment operator for a matrix class? 如何在 class 中编写优化的构造函数 &gt; - How to write optimized constructor in a class > 如果类成员是向量,我们是否应该显式编写复制构造函数? - Should we explicitly write a copy constructor if the class member is a vector?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM