gpt4 book ai didi

c++ - 我应该如何为我的类编写构造函数

转载 作者:搜寻专家 更新时间:2023-10-31 00:50:18 24 4
gpt4 key购买 nike

我有一个容器类,我可以向其发送一个 Geometry 对象作为构造函数参数。

Geometry 是一个多态类,作为其他几何类型(如 Sphere 和 Rectangle)的接口(interface)。

我的问题是,在 Container 类中,带有参数“Container(std::string str, Geometry* geometry)”的构造函数是否可以以更灵活的方式进行编码。

每当我向 Geometry 添加一个新的子类时,我都需要在容器类构造函数中编写另一个 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;
}

};

////////////////构造函数类的定义/////////////////////

#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;
}
};

最佳答案

你的设计全是落后的,结果就是你在做Container负责计算出所有Geometry的类型传递给它的对象,以便复制它们。那将使你的Container维护噩梦 - 如果有人创建另一个派生自 Geometry 的类, 他们可能会忘记修改 Container相应地。

您还省略了与您的问题相关的代码(如虚拟析构函数)并包含了与问题无关的代码(std::string 成员的声明,以及在构造函数和其他虚函数中对它们的初始化)。

相反,将类设置为 Geometry 会更好及其派生类,负责复制自身。

核心是 Geometry类本身

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

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

(为方便起见,我省略了 std::string 成员)。然后派生类覆盖 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

Clone() Geometry 中的函数是纯虚拟的,所以派生类不能被实例化,除非你记得重写它。

克隆的责任在于Geometry及其派生类 - 如果类派生自 Geometry,编译器将有助于诊断错误这不会覆盖 Clone()功能。

然后,所有一个Container需要做的就是有一个成员(member)std::unique_ptr<Geometry>或(如果您打算拥有一组)std::vector<std::unique_ptr<Geometry> > .对于 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;
};

我使用 std::unique_ptr<Geometry> 的原因在上面(而不是 Geometry * 在你的代码中)是 std::unique_ptr<>避免需要明确决定何时销毁 Geometry对象。

Container 的无参数构造函数初始化为包含空 Geometry (即空指针)。

Container 的构造函数接受 Geometry *克隆传递的对象,并且不承担它的所有权。这意味着调用者对其传递的对象的生命周期负责。这与你的main()是一致的, 构造自动存储时长的对象。

请注意,我遵循“三原则”——如果定义了复制构造函数、复制赋值或析构函数的非默认版本,那么其他两个也应该定义。 operator=()上面的工作方式与复制构造函数一致(即它克隆 Container 中的对象,而不是导致 Geometry 对象在 Container 之间共享)。析构函数被明确定义为默认值,因为 Container没有明确管理其成员的生命周期(std::unique_ptr 的析构函数完成了这项工作)。

关于c++ - 我应该如何为我的类编写构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57932237/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com