使用c'ctor,d'ctor和覆盖
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用c'ctor,d'ctor和覆盖相关的知识,希望对你有一定的参考价值。
假设我想定义一个名为Circle
的类,它有计算其面积和周长的方法。该类使用另一个名为Point
的类。还假设该类继承自名为Shape
的抽象类。
所以,我写了以下代码:
circle.h
#ifndef Circle_h
#define Circle_h
#include "Point.h"
#include "Shape.h"
class Circle : public Shape
{
public:
Circle(const Point &ceneter , int radius);
~Circle();
virtual double getArea() const ;
virtual double getPerim() const ;
private:
int radius;
Point center;
};
#endif
shape.h
#ifndef Shape_h
#define Shape_h
#include "Point.h"
#include <iostream>
class Shape //abstract class//
{
public:
virtual double getArea() const=0;
virtual double getPerim() const=0;
};
#endif
point.h
#ifndef Point_h
#define Point_h
class Point
{
public:
Point(int x, int y);
~Point();
int getX() const;
int getY() const;
void setX(int x);
void setY(int y);
private:
int x, y;
};
#endif
我不太确定两件事:
- 我应该在
Shape
课程中加入c'tor和d'ctor吗? 因为据我所知,因为那个类是抽象的,所以没有必要。 - 我应该将
override
添加到Circle
中的重写方法中吗?virtual double getArea() const override ; virtual double getPerim() const override ;
- 假设我写了以下(主要):
Point o(0, 0); Point a(0, 1); Point b(1, 0); Shape *shapes[] = { new Circle(a, 2), new Circle(b,3), new Circle(o, 1 };
最后一行如何影响使用(或不使用)ctor和dtor的需要?
你的Shape
课程不需要ctor但是建议给它一个virtual
dtor:
class Shape {
public:
virtual ~Shape() = default;
// ...
};
没有这个virtual
析构函数,它是通过指向delete
的Shape
对象的未定义行为:没有具体类型可以是动态类型Shape
但是当dtor不是delete
时,通过具有不同静态类型的指针的virtual
ing对象是未定义的行为。
关于override
的使用我推荐使用它!虽然在一个简单的例子中它可能并不重要,例如你展示的那个,它会在类层次结构增长时变得相关。任何成功的软件都会增长,它会增加virtual
功能,代码清晰度有助于维护。 ......我更愿意为成功做好准备。
如上所述,这些类都不需要复制构造函数或析构函数。这是因为所有成员都是简单的值,不需要任何更多的值副本或简单地释放内存。
当类具有编译器无法知道如何释放的资源(例如文件句柄)时,需要dtor。
我应该为Circle中的重写方法添加覆盖,像这样吗?
恕我直言,这个词增加了价值。
假设我写了以下(主要):
Point o(0, 0);
Point a(0, 1);
Point b(1, 0);
Shape* shapes[] = { new Circle(a, b),
new Circle(o, a, b),
new Circle(o, 1) };
有了这些行,我的编译器现在报告了2个额外的错误(带有2个音符)......
error: no matching function for call to ‘Circle::Circle(Point&, Point&)’
note: no known conversion for argument 2 from ‘Point’ to ‘int’
也
error: no matching function for call to ‘Circle::Circle(Point&,Point&,Point&)’
note: candidate expects 2 arguments, 3 provided
最后一行是否会影响使用(或不使用)c'tor和d'tor的需要?
我想不是。
甚至在此“代码添加”之前,编译器就会提供有关虚拟功能和可访问的非虚拟代码的警告。这些警告可以通过声明(丢失)dtors虚拟来修复,但是......好吧,这里他们只是指出你的代码编译不干净。
你应该完成你的[MCVE]。因此,您提供的信息不足以“仔细挑选”您所做或不提供的内容(ctors,dtors)。
我通常以另一种方式来解决这些问题。我的个人编码“标准”包括以下6个想法,当我有疑问或不明白为什么时,我只是将这些行添加到我的课程中,在私人部分。
// coding standard: disallow when not used
T(void) = delete; // default ctor (1)
~T(void) = delete; // default dtor (2)
T(const T&) = delete; // copy ctor (3)
T(const T&&) = delete; // move ctor (4)
T& operator= (const T&) = delete; // copy assignment (5)
T& operator= (const T&&) = delete; // move assignment (6)
通过'T',我的意思是你用你的班级名称替换'T'。它很简单,所以我通常会添加到每个类中。即,在每个类的私人区域中重复上述6行,并替换T.
现在,您的编译器可以抱怨特定的内容。我发现很快就能学会如何解决这个问题,所以我举了一个例子。
如果您获得MCVE,请尝试以下添加:
class Shape //abstract class//
{
public:
virtual double getArea() const=0;
virtual double getPerim() const=0;
private:
// coding standard - disallow when not used
Shape(void) = delete; // default ctor (1)
~Shape(void) = delete; // default dtor (2)
Shape(const Shape&) = delete; // copy ctor (3)
Shape(const Shape&&) = delete; // move ctor (4)
Shape& operator= (const Shape&) = delete; // copy assignment (5)
Shape& operator= (const Shape&&) = delete; // move assignment (6)
};
由于Shape类只有编译器注入了默认的ctor,(和dtor)我认为这些删除会在编译器中触发错误。
这个想法很简单,如果'其他代码'(例如标准容器,算法或编译器)使用Shape做事并使用一个或添加这些中的一个或多个,编译器会注意到它们被删除,并生成给你一个错误。
我对标准容器感到惊讶,因为他们经常使用这些容器中的6个以上。删除ctor后,我有机会决定是否要编写特定于此项工作的内容,或者如果编译器提供的默认值可能正常......通常是这样。在这种情况下,我只是注释掉6个删除行中的一个或多个,然后再次编译。
我拒绝评论这些删除。有时它会发生我的一个错误会触发其中一个的使用。也要注意那些。
- 摘要
这6行(以及您可能选择考虑的其他行)将让您了解编译器提供的“服务”方法。 (大多数时候,我也不喜欢隐含的转换。)
因此,这种技术不是试图理解为什么你可能想要或不想要这些6,而是让你找出你的程序需要什么。使用每一行(即禁用至少足够长的时间以查看位置和内容),编译器投诉显示正在使用“移动ctor”或“移动分配”的位置。当你知道你没有这样做时非常有帮助!
以上是关于使用c'ctor,d'ctor和覆盖的主要内容,如果未能解决你的问题,请参考以下文章
C++11 - CTOR() = default 和空 CTOR() 有啥区别? [复制]
加载C:\PROGRA~1\COMMON~1\INSTAL~1\PROFES~1\RUNTIME\0700\INTEL32\Ctor.d