Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C++; A类{ 公众: ~A(){release();} 虚拟发布(){cout_C++ - Fatal编程技术网

C++ 在C++; A类{ 公众: ~A(){release();} 虚拟发布(){cout

C++ 在C++; A类{ 公众: ~A(){release();} 虚拟发布(){cout,c++,C++,析构函数是以构造函数的相反顺序执行的,因此当AB中的A被销毁时,其B组件已经被销毁并且不再存在。对已销毁对象调用方法会产生未定义的行为,这就是为什么对虚拟方法的调用总是解析为当前cl构造函数或析构函数中的ass类型 所以基本上不,你不能这样做。你必须把它们全部写出来。不要从析构函数或构造函数调用虚拟方法-它们不会做你期望它们做的事情 停止懒惰,编写析构函数。这种问题的解决方案是一个预销毁阶段,您可以手动控制销毁的发生方式 使用pImpl模式实现您的对象。当包装对象被销毁时,请在销毁之前通知pIm

析构函数是以构造函数的相反顺序执行的,因此当A
B
中的
A
被销毁时,其
B
组件已经被销毁并且不再存在。对已销毁对象调用方法会产生未定义的行为,这就是为什么对虚拟方法的调用总是解析为当前cl构造函数或析构函数中的ass类型


所以基本上不,你不能这样做。你必须把它们全部写出来。

不要从析构函数或构造函数调用虚拟方法-它们不会做你期望它们做的事情


停止懒惰,编写析构函数。

这种问题的解决方案是一个预销毁阶段,您可以手动控制销毁的发生方式

使用
pImpl
模式实现您的对象。当包装对象被销毁时,请在销毁之前通知
pImpl

pImpl
可以有一个基本的
virtual PreDestroyable
类,该类允许子方法注册
predestrouction
回调,您可以在预销毁阶段调用该回调

class A {
public:
  ~A() { release(); }
  virtual release() { cout << "~A"; } 
}

class B : public A {
  release() { cout << "~B"; }
}
类可销毁{
受保护的:
Destroyable(){};//必须为空
virtual~Destroyable(){Assert(PreDestroyers.empty());};
void RegisterPreDestroy(std::function const&func){PreDestroyers.push_back(func));
私人:
std::病媒预雌雄体;
公众:
//反向顺序,可重入:
无效准备就绪(){
而(!PreDestroyers.empty()){
auto f=PreDestroyers.back();
PreDestroyers.pop_back();
f();
}        
}
};
//处理注册:
模板
类HasPreDestroyCode:公共虚拟可销毁{
//TODO:常规CRTP静态或动态检查:
T*self(){return static_cast(this);}
T const*self()const{return static_cast(this);}
HasPreDestroyCode(){
RegisterRedestory([&](){self()->PreDestroy();});
}
HasPreDestroyCode(HasPreDestroyCode常量和其他){
RegisterRedestory([&](){self()->PreDestroy();});
}
HasPreDestroyCode(HasPreDestroyCode常量和其他){
RegisterRedestory([&](){self()->PreDestroy();});
}
私人:
HasPreDestroyCode和运算符=(HasPreDestroyCode常量和其他)=删除;
};
类测试:HasPreDestroyCode{
公众:
void PreDestroy(){}
};

我上一次写这篇文章是在C++11之前,所以我还没有弄清楚如何处理移动构造它。这一切都是在运行时完成的,而像上面这样用较少的运行时数据来完成可能是可行的。类似于层次结构中包含预销毁代码的类型列表之类的东西?

您希望这两种类型都被调用吗ed?不,是唯一的子版本()方法。销毁应该从最派生的类型开始,并向后工作到基本版本。如果在基本版本中调用虚拟版本()方法,该方法位于派生类型中,其析构函数已被调用,因此没有可访问或处理的有效成员。您希望执行什么操作。即使它按您期望的方式工作(但实际情况并非如此)你不能做任何有用的事情,所以不要做它。问题变成了你真正想要达到的目标?你应该在析构函数中清理,为什么不去做呢?我不明白你为什么要重新发明C++对象系统。我自己没想过,谢谢,这完全有道理:)
class Destroyable {
protected:
  Destroyable() {}; // must be empty
  virtual ~Destroyable() { Assert(PreDestroyers.empty()); };
  void RegisterPreDestroy( std::function<void()> const& func ) { PreDestroyers.push_back(func) );
private:
  std::vector<std::function<void()>> PreDestroyers;
public:
  // reverse order, reentrant:
  void PrepareToDie() {
    while (!PreDestroyers.empty()) {
      auto f = PreDestroyers.back();
      PreDestroyers.pop_back();
      f();
    }        
  }
};

// handles registration:
template<typename T>
class HasPreDestroyCode: public virtual Destroyable {
  // TODO: usual CRTP static or dynamic checks:
  T* self() { return static_cast<T*>(this); }
  T const* self() const { return static_cast<T*>(this); }
  HasPreDestroyCode() {
    RegisterPreDestroy( [&]() { self()->PreDestroy(); } );
  }
  HasPreDestroyCode( HasPreDestroyCode const& other ) {
    RegisterPreDestroy( [&]() { self()->PreDestroy(); } );
  }
  HasPreDestroyCode( HasPreDestroyCode const& other ) {
    RegisterPreDestroy( [&]() { self()->PreDestroy(); } );
  }
private:
  HasPreDestroyCode& operator=( HasPreDestroyCode const& other ) = delete;
};

class Test: HasPreDestroyCode<Test> {
public:
  void PreDestroy() {}
};