在c++中是否有可能像java中允许的那样,在分配过程中给出类的定义?

Is it possible to give a definition of a class in C++ during allocation, as is allowed in java

本文关键字:过程中 分配 定义 java 有可能 c++ 是否      更新时间:2023-10-16

或者直接输入

我可以做一些像

class A {
public:
  virtual void foo() = 0;
};
class B {
  public:
    A *a;
    b(){
       a = new A() { void foo() {printf("hello");}
    }
};

不,c++没有像Java那样的匿名类。

你可以定义本地类,像这样:

class B {
  public:
    A *a;
    b(){
       struct my_little_class : public A {
           void foo() {printf("hello");}
       };
       a = new my_little_class();
    }
};

或者只是一个嵌套类:

class B {
  private:
    struct my_little_class : public A {
        void foo() {printf("hello");}
    };
  public:
    A *a;
    b(){
       a = new my_little_class();
    }
};

在c++ 03中,局部类有一些限制(例如,它们不能用作模板形参),这些限制在c++ 11中取消了。

在Java中,匿名类有时被用来做其他语言对匿名函数所做的事情,例如,当您创建Runnable的匿名实现时。c++ 11有匿名函数(也称为lambdas),因此如果这是您想要实现的目标,那么这可能是一个选项。

与其他答案相同,但如果您希望模仿这种行为,您可以(但我不建议这样做):

    struct          Interface
    {
      virtual void  doStuff() const = 0;
      virtual       ~Interface() {}
    };
    #define newAnon(tmp_name, parents, body, args...)                       
      ({                                                                    
        class              tmp_name :                                      
          parents                                                           
        {                                                                   
          body;                                                             
        };                                                                  
        new tmp_name(##args);                                               
      })
    Interface       *getDefault()
    {
      return newAnon(__tmp__, public Interface,
public:
                     virtual void doStuff() const {
                       std::cout << "Some would say i'm the reverse" << std::endl;
                     });
    }

但是要注意,因为在这个新类中不能有静态成员,这是在利用Gcc/g++语句表达式:静态成员的解决方案如下,假设我们想要一个静态int i,它在前面的类tmp的几种情况下自增,它看起来像这样:

    struct          Interface
    {
      virtual void  doStuff() const = 0;
      virtual void  undoStuff() const = 0;
      virtual       ~Interface() {}
    };
    newAnon(__tmp__, Interface,
                     static int &i() {
                       static int i(0);
                       return i;
                     }
public:    
                     virtual void doStuff() const {
                       std::cout << "call n°" << i()++ << std::endl;
                     }
                     virtual void undoStuff() const {
                       std::cout << "uncall n°" << i()-- << std::endl;
                     });

结果是getDefault()给出的所有新指针都指向同一个整数。请注意,使用c++11的auto,您可以访问所有公共成员,并使用层次结构创建所述类型的子类型:

  auto tmp = newAnon(...);
  struct Try : decltype(*tmp+) {
    Try() { std::cout << "Lol" << std::endl; }
  };
  Try a; // => will print "Lol"

更新:没有扩展的更现代的c++(14-17)应该是

#define newAnon(code...) 
     [&](auto&&... args) {
          struct __this__ : code;
          return std::make_unique<__this__>(std::forward<decltype(args)>(args)...); 
      }
auto ptr = new_anon(interface { ... })(arguments);

No.

但是这种习惯用法在Java中传递回调给API时很常见。如果这是您想要的(为API注册回调),您可能希望使用信号,就像在Boost上实现的那样。信号或libsigc++(在这种情况下最好的方法)。

此外,在语法上更接近你想要的,新的c++规范(c++ 11,由大多数最新的编译器支持)也允许lambda函数:

template<class F>
void func(F callable) {
  callable(); // Callable is an object that can be called as a function.
}
void a() {
  method([]() {
    printf("hello");
  }); // This anonymous function was defined here...
}

如果你真的想"动态地"定义一个新类,它不能在内联中完成,但可以在"上面"完成:

class A {
public:
  virtual void foo() = 0;
};
class B {
  public:
    A *a;
    void b(){
       class MyImplementation: public A { 
         public: void foo() { printf("hello"); }
       };
       a = new MyImplementation();
    }
};

类甚至可以是匿名的,但是你只能在堆栈上创建对象(即你不能在匿名类上使用new,并且在function返回时它将被释放):

void function_that_uses_but_does_not_stores_A(A* obj);
void function(){
    class : public A { 
         public: void foo() { printf("hello"); }
    } obj;
    function_that_uses_but_does_not_stores_A(&obj);
 };

No。c++中的所有内容都必须在使用之前进行定义。在您的情况下,由于您想要覆盖A::foo(),您必须派生一个新类,然后B可以实例化该类,例如:

class A
{ 
public: 
  virtual void foo() = 0; 
}; 
class A1 : public A
{
public:
  void foo() { printf("hello"); }
}; 
class B
{ 
public: 
  A *a; 
  B()
  { 
    a = new A1(); 
  } 
};