C++ 如何向未命名类添加构造函数/析构函数?

C++ 如何向未命名类添加构造函数/析构函数?,c++,class,constructor,destructor,declaration,C++,Class,Constructor,Destructor,Declaration,有没有办法在未命名类中声明构造函数或析构函数?考虑下面的 void f() { struct { // some implementation } inst1, inst2; // f implementation - usage of instances } 后续问题:实例当然是作为任何基于堆栈的对象构造(和销毁)的。叫什么名字?它是由编译器自动指定的一个损坏的名称吗 无法为未命名类声明构造函数或析构函数,因为构造函数和析构函数名称需要与类名匹配。在

有没有办法在未命名类中声明构造函数或析构函数?考虑下面的

void f()
{
    struct {
        // some implementation
    } inst1, inst2;

    // f implementation - usage of instances
}

后续问题:实例当然是作为任何基于堆栈的对象构造(和销毁)的。叫什么名字?它是由编译器自动指定的一个损坏的名称吗

无法为未命名类声明构造函数或析构函数,因为构造函数和析构函数名称需要与类名匹配。在您的示例中,未命名的类是本地类。它没有链接,所以没有创建名称。

< P>如果你在考虑C++名字,那么任何有对象的类都必须有一个析构函数,不管你显式创建还是不显式创建。是的,编译器知道如何分配名称。然而,这种命名约定是否与您的业务有关,可能不是

实际上,您可以创建一个结构,也可以创建一个没有名称的命名空间。您仍然需要在某个地方有名称,因为在链接所有这些内容时,链接器需要某种名称才能使其正常工作,尽管在许多情况下,它将是本地名称,在编译时由汇编程序立即解析


了解编译器指定的名称的一种方法是查看调试字符串,并查看与您感兴趣的不同地址对应的内容。当您使用-g编译时,您应该获得所有必要的调试,以便调试器使用正确的“名称”将当前代码放置在正确的位置。。。(我见过没有名称的名称空间,上面写着“namespace”,我很确定结构在更高的层次上使用了相同的技巧。)

最简单的解决方案是将命名结构实例作为未命名实例中的成员,并将所有功能放入命名实例中。这可能是与C++98兼容的唯一方法

#include <iostream>
#include <cmath>
int main() {
   struct {
      struct S {
         double a;
         int b;
         S() : a(sqrt(4)), b(42) { std::cout << "constructed" << std::endl; }
         ~S() { std::cout << "destructed" << std::endl; }
      } s;
   } instance1, instance2;
   std::cout << "body" << std::endl;
}
由于
c
的实例将占用一些空间,因此我们最好明确地说明它,并去掉助手。下面的代码有点C++11习惯用法的味道,但由于return语句的缘故,有点冗长

struct {
   double a { sqrt(4) };
   int b { 42 };
   char constructor { [this]{
      std::cout << "constructed" << std::endl;
      return char(0);
  }() };
}

不幸的是,似乎无法从
ConstructDestruct
中删除函数指针。但这并不是那么糟糕,因为它的大小必须是非零。在未命名结构之后立即存储的任何内容都可能与函数指针大小的倍数对齐,因此
sizeof(ConstructDestruct)
大于1时可能不会产生开销。

@πάνταῥεῖ 显然我需要睡一会儿。这个问题显然是探索性的。我知道你不能,至少不是通常的方式。标准读取构造函数没有名称。一种特殊的声明器语法,使用可选函数说明符(7.1.2),后跟构造函数的类名,后跟参数列表,用于在没有名称时声明或定义构造函数,但不能这样做。我感兴趣的是工作区的存在和实际调用的机制为什么不直接命名它们?让调试一开始就更容易。我不是在暗示我有一个拒绝命名的类型(在我的代码中),也不是说匿名类是我的一种实践。我只是在探索对构造函数/析构函数的隐含调用的机制,并寻找一种在学术意义上对我非常感兴趣的解决方法。如果这个问题是我的问题,我很抱歉。@NikosAthanasiou“……匿名类也不是我的实践……”从技术上讲,这是一个未命名的类(如你在问题中所述),而不是“匿名类”。未命名类是允许的,(尽管C++中允许的类可能会改变,但它们不是C++ 11)。非常有趣的方法!尤其是用lambda构造的
char
。注意,在VC++上,它会抱怨将
0
强制转换为
char
(因为返回值不是显式的
char
)。也许使用bool更干净?在我看来,值初始化技巧不适用于未命名的
/
结构
基类型。此外,它也不允许向成员提供(合理的)解释理由。但还是很高兴知道!
int b { [this]{ constructor(); return 42; }() };
void constructor() {
   std::cout << "constructed" << std::endl;
}
#include <iostream>
#include <cmath>
struct Construct {
   template <typename T> Construct(T* instance) {
      instance->constructor();
   }
};

int main() {
   struct {
      double a { sqrt(4) };
      int b { 42 };
      Construct c { this };
      void constructor() {
         std::cout << "constructed" << std::endl;
      }
   } instance1, instance2;
}
struct {
   double a { sqrt(4) };
   int b { 42 };
   char constructor { [this]{
      std::cout << "constructed" << std::endl;
      return char(0);
  }() };
}
#include <iostream>
#include <cmath>
struct ConstructDestruct {
   void * m_instance;
   void (*m_destructor)(void*);
   template <typename T> ConstructDestruct(T* instance) :
      m_instance(instance),
      m_destructor(+[](void* obj){ static_cast<T*>(obj)->destructor(); })
   {
      instance->constructor();
   }
   ~ConstructDestruct() {
      m_destructor(m_instance);
   }
};

int main() {
   struct {
      double a { sqrt(4) };
      int b { 42 };
      ConstructDestruct cd { this };

      void constructor() {
         std::cout << "constructed" << std::endl;
      }
      void destructor() {
         std::cout << "destructed" << std::endl;
      }
   } instance1, instance2;
   std::cout << "body" << std::endl;
}
#include <iostream>
#include <cmath>
#include <cstddef>

template <std::ptrdiff_t> struct MInt {};

struct ConstructDestruct {
   void (*m_destructor)(ConstructDestruct*);
   template <typename T, std::ptrdiff_t offset>
   ConstructDestruct(T* instance, MInt<offset>) :
      m_destructor(+[](ConstructDestruct* self){
         reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(self) - offset)->destructor();
      })
   {
      instance->constructor();
   }
   ~ConstructDestruct() {
      m_destructor(this);
   }
};
#define offset_to(member)\
   (MInt<offsetof(std::remove_reference<decltype(*this)>::type, member)>())

int main() {
   struct {
      double a { sqrt(4) };
      int b { 42 };
      ConstructDestruct cd { this, offset_to(cd) };
      void constructor() {
         std::cout << "constructed " << std::hex << (void*)this << std::endl;
      }
      void destructor() {
         std::cout << "destructed " << std::hex << (void*)this << std::endl;
      }
   } instance1, instance2;
   std::cout << "body" << std::endl;
}