C++ 为什么在C++;?
我知道需要一个虚拟析构函数。但是为什么我们需要一个纯粹的虚拟析构函数呢?在C++文章中,作者提到了在想抽象类时使用纯虚析构函数。p> 但我们可以通过将任何成员函数作为纯虚函数来抽象类 所以我的问题是C++ 为什么在C++;?,c++,destructor,pure-virtual,C++,Destructor,Pure Virtual,我知道需要一个虚拟析构函数。但是为什么我们需要一个纯粹的虚拟析构函数呢?在C++文章中,作者提到了在想抽象类时使用纯虚析构函数。p> 但我们可以通过将任何成员函数作为纯虚函数来抽象类 所以我的问题是 什么时候我们才能真正使析构函数成为纯虚拟的?谁能给出一个好的实时示例 当我们创建抽象类时,使析构函数也是纯虚拟的是一种好做法吗?如果是,为什么 1) 当需要派生类进行清理时。这是罕见的 2) 不,但是你希望它是虚拟的 允许使用纯虚拟析构函数的真正原因可能是,禁止它们意味着在语言中添加另一条规则,并且
注意:析构函数是唯一一种方法,即使它是纯虚拟的也有一个实现来实例化派生类(是的,纯虚拟函数可以有实现)
如果要创建抽象基类,请执行以下操作:
- 无法实例化的(是的,这与术语“抽象”是多余的!)
- 但是需要虚拟析构函数行为(您打算携带指向ABC的指针,而不是指向派生类型的指针,并通过它们进行删除)
您可以保证它不能被实例化(即使是在类本身内部,这就是为什么私有构造函数可能不够用),您可以为析构函数获得所需的虚拟行为,并且您不必找到另一个不需要虚拟分派的方法并将其标记为“virtual”.抽象类所需的只是至少一个纯虚函数。任何功能都可以;但事实上,析构函数是任何类都会有的,所以它总是作为候选者存在。此外,使析构函数纯虚拟(而不仅仅是虚拟)除了使类抽象之外,没有任何行为副作用。像这样的许多样式指南建议一致使用纯虚拟析构函数来指示类是抽象的,除非它提供了一个一致的位置,阅读代码的人可以查看该类是否是抽象的。如果您想停止实例化基类而不对已存在的类进行任何更改实现并测试派生类,则在基类中实现纯虚拟析构函数 我们需要使析构函数虚拟化,因为如果我们不使析构函数虚拟化,那么编译器只会破坏基类的内容,n所有派生类都将保持不变,因为编译器不会调用除基类之外的任何其他类的析构函数。你问了一个例子,我相信下面提供了一个纯虚拟析构函数的理由。我期待着答复这是否是一个好的理由 我不希望任何人能够抛出
error\u base
类型,但是异常类型error\u oh\u shucks
和error\u oh\u blast
具有相同的功能,我不想写两次。pImpl的复杂性对于避免将std::string
暴露给我的客户机是必要的,而使用std::auto_ptr
则需要复制构造函数
public标头包含异常规范,客户端可以使用这些规范来区分my library引发的不同类型的异常:
// error.h
#include <exception>
#include <memory>
class exception_string;
class error_base : public std::exception {
public:
error_base(const char* error_message);
error_base(const error_base& other);
virtual ~error_base() = 0; // Not directly usable
virtual const char* what() const;
private:
std::auto_ptr<exception_string> error_message_;
};
template<class error_type>
class error : public error_base {
public:
error(const char* error_message) : error_base(error_message) {}
error(const error& other) : error_base(other) {}
~error() {}
};
// Neither should these classes be usable
class error_oh_shucks { virtual ~error_oh_shucks() = 0; }
class error_oh_blast { virtual ~error_oh_blast() = 0; }
exception_string类保持私有,从我的公共接口隐藏std::string:
// exception_string.h
#include <string>
class exception_string {
public:
exception_string(const char* message) : message_(message) {}
const char* get() const { return message_.c_str(); }
private:
std::string message_;
};
这里我想告诉大家什么时候需要虚拟析构函数,什么时候需要纯虚拟析构函数
class Base
{
public:
Base();
virtual ~Base() = 0; // Pure virtual, now no one can create the Base Object directly
};
Base::Base() { cout << "Base Constructor" << endl; }
Base::~Base() { cout << "Base Destructor" << endl; }
class Derived : public Base
{
public:
Derived();
~Derived();
};
Derived::Derived() { cout << "Derived Constructor" << endl; }
Derived::~Derived() { cout << "Derived Destructor" << endl; }
int _tmain(int argc, _TCHAR* argv[])
{
Base* pBase = new Derived();
delete pBase;
Base* pBase2 = new Base(); // Error 1 error C2259: 'Base' : cannot instantiate abstract class
}
类基
{
公众:
Base();
virtual~Base()=0;//纯虚拟,现在没有人可以直接创建基对象
};
Base::Base(){cout从我读到的对你问题的回答中,我无法推断出一个实际使用纯虚拟析构函数的好理由。例如,以下理由根本无法说服我:
允许使用纯虚拟析构函数的真正原因可能是,禁止它们意味着在语言中添加另一条规则,并且没有必要使用此规则,因为允许使用纯虚拟析构函数不会产生任何不良影响
在我看来,纯粹的虚拟德
// exception_string.h
#include <string>
class exception_string {
public:
exception_string(const char* message) : message_(message) {}
const char* get() const { return message_.c_str(); }
private:
std::string message_;
};
#include "error.h"
throw error<error_oh_shucks>("That didn't work");
// client.cpp
#include <error.h>
try {
} catch (const error<error_oh_shucks>&) {
} catch (const error<error_oh_blast>&) {
}
class Base
{
public:
Base();
virtual ~Base() = 0; // Pure virtual, now no one can create the Base Object directly
};
Base::Base() { cout << "Base Constructor" << endl; }
Base::~Base() { cout << "Base Destructor" << endl; }
class Derived : public Base
{
public:
Derived();
~Derived();
};
Derived::Derived() { cout << "Derived Constructor" << endl; }
Derived::~Derived() { cout << "Derived Destructor" << endl; }
int _tmain(int argc, _TCHAR* argv[])
{
Base* pBase = new Derived();
delete pBase;
Base* pBase2 = new Base(); // Error 1 error C2259: 'Base' : cannot instantiate abstract class
}
struct IParams
{
IParams(const ModelConfiguration& aModelConf);
virtual ~IParams() = 0;
void setParameter(const N_Configuration::Parameter& aParam);
std::map<std::string, std::string> m_Parameters;
};
struct NumericsParams : IParams
{
NumericsParams(const ModelConfiguration& aNumericsConf);
virtual ~NumericsParams();
double dt() const;
double ti() const;
double tf() const;
};
struct PhysicsParams : IParams
{
PhysicsParams(const N_Configuration::ModelConfiguration& aPhysicsConf);
virtual ~PhysicsParams();
double g() const;
double rho_i() const;
double rho_w() const;
};
virtual ~Fruit() = 0; // pure virtual
Fruit::~Fruit(){} // destructor implementation
class Printable {
virtual void print() const = 0;
// virtual destructor should be here, but not to confuse with another problem
};
class Printer {
void queDocument(unique_ptr<Printable> doc);
void printAll();
};
class Destroyable {
virtual ~Destroyable() = 0;
};
class PostponedDestructor {
// Queues an object to be destroyed later.
void queObjectForDestruction(unique_ptr<Destroyable> obj);
// Destroys all already queued objects.
void destroyAll();
};