[英]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.