我是一名c ++初学者,学习智能指针和继承。我有一个基类Shape
(抽象),作为派生类,我有Triangle,Isosceles和Equilateral。
我的想法是根据指向基类的类型为每个类打印适当的打印消息,我在main()中声明了如下所示。
#include <iostream>
#include <memory>
class Shape
{
public:
virtual const void triangle()const = 0;
virtual ~Shape(){ std::cout<<"Shape Deleted\n"; }
};
class Triangle: public Shape
{
public:
virtual const void triangle()const override
{ std::cout<<"I am a triangle\n"; }
virtual ~Triangle(){ std::cout<<"Triangle Deleted\n"; }
};
class Isosceles : public Triangle
{
public:
virtual const void triangle()const override
{ std::cout<<"I am an isosceles triangle\n"; }
virtual ~Isosceles(){ std::cout<<"Isosceles Deleted\n"; }
};
class Equilateral: public Isosceles
{
public:
virtual const void triangle()const override
{ std::cout<<"I am an equilateral triangle\n"; }
virtual ~Equilateral(){ std::cout<<"Equilateral Deleted\n"; }
};
当我使用传统方式使用new
关键字创建指针对象时,所有类的析构函数都能完美地工作(下面给出了输出)。
main()
是:
int main()
{
Shape *Obj[3];
Obj[0] = new Equilateral();
Obj[1] = new Isosceles();
Obj[2] = new Triangle();
for(auto it: Obj)
it->triangle();
delete Obj[0];
return 0;
}
但是当我改为std::shared_ptr
时,事情就不同了,我无法理解。
main()
是:
int main()
{
std::shared_ptr<Shape> obj[3];
obj[0] = std::make_shared<Equilateral>();
obj[1] = std::make_shared<Isosceles>();
obj[2] = std::make_shared<Triangle>();
for(auto it: obj)
it->triangle();
return 0;
}
任何人都可以帮我搞清楚,为什么会这样? 可以提前感谢。
答案 0 :(得分:1)
使用原始指针时,只会销毁第一个对象:
delete Obj[0];
并使其他2个泄漏,而当您使用std::shared_ptr
正确清理所有3个对象时。这就是建议使用智能指针的确切原因。
答案 1 :(得分:0)
实际上你的第二个片段是正确的,输出完全符合预期。
您的第一个代码段有一个错误:您只是public string tables(string strFileName)
{
DataTable dt = null;
try
{
recarrega = false;
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.15.0;Data Source=" + strFileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";");
conn.Open();
dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
conn.Close();
}
catch (Exception a)
{
MessageBox.Show("15 - " + a.Message);
try
{
recarrega = false;
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.14.0;Data Source=" + strFileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";");
conn.Open();
dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
conn.Close();
}
catch (Exception b)
{
MessageBox.Show("14 - " + b.Message);
try
{
recarrega = false;
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.13.0;Data Source=" + strFileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";");
conn.Open();
dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
conn.Close();
}
catch (Exception c)
{
MessageBox.Show("13 - " + c.Message);
try
{
recarrega = false;
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + strFileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";");
conn.Open();
dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
conn.Close();
}
catch (Exception d)
{
MessageBox.Show("12 - " + d.Message);
}
}
}
}
}
。那么delete obj[0];
和obj[1]
怎么样?如果删除数组的所有成员,您将看到两个代码示例的输出之间的差异消失。
关于智能指针的好处是它们应该用于“即发即忘”的庄园。
最后,请仔细阅读你的那本书:在开始任何有关OOP的事情之前,你需要掌握构造和破坏的顺序。