是否可以在 C++ 中给出类的定义?在分配期间,正如java中允许的那样

发布于 2024-12-19 04:32:47 字数 204 浏览 4 评论 0原文

或者简单地说

我可以做一些事情吗

class A {
public:
  virtual void foo() = 0;
};

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

Or simply put

can I do some thing like

class A {
public:
  virtual void foo() = 0;
};

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

翻了热茶 2024-12-26 04:32:47

不,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 具有匿名函数(也称为 lambda),因此如果这是您想要实现的目标,那么这可能是一个选择。

No, C++ doesn't have anonymous classes like Java's.

You can define local classes, like this:

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

Or maybe just a nested class:

class B {
  private:
    struct my_little_class : public A {
        void foo() {printf("hello");}
    };

  public:
    A *a;

    b(){
       a = new my_little_class();
    }
};

In C++03, local classes have some limitations (for example, they can't be used as template parameters) that were lifted in C++11.

In Java, anonymous classes are sometimes used to do what other languages do with anonymous functions like, for example, when you create an anonymous implementation of Runnable. C++11 has anonymous functions (also known as lambdas), so that could be an option if this is what you're trying to achieve.

我ぃ本無心為│何有愛 2024-12-26 04:32:47

与其他人的答案相同,但如果您想模拟这种行为,您可以(但我不推荐):

    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++ 语句表达式 : Statement-Exprs

静态成员的解决方案是是下面,假设我们想要一个静态 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);

Same answer as for the others, but if you wish to emulate such behavior you can (I don't recommend it though) :

    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;
                     });
    }

Beware though because you cannot have a static member in this new class, and that this is taking advantage of the Gcc/G++ statement expression : Statement-Exprs

A solution for static member would be the following, imagine we want a static int i that increments itself in a few situations in our previous class tmp, this would look like this :

    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;
                     });

The result is that all new pointers given by getDefault() will refer to the same integer.
Note that using c++11's auto you can access all the public members as expected and use hierarchy to create a child of said type :

  auto tmp = newAnon(...);

  struct Try : decltype(*tmp+) {
    Try() { std::cout << "Lol" << std::endl; }
  };

  Try a; // => will print "Lol"

Update:
A more modern c++ (14-17) without extensions would be

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

auto ptr = new_anon(interface { ... })(arguments);
鱼忆七猫命九 2024-12-26 04:32:47

不会。

但是在 Java 中向 API 传递回调时,这种习惯用法很常见。如果这是您想要的(注册 API 的回调),您可能需要使用信号,例如在 Boost.Signalslibsigc++ (最好的方法在这个 案件)。

此外,在语法上更接近您想要的,新的 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.

But this idiom is frequent in Java when passing callbacks to an API. If this is what you want (register callbacks for an API), you may want to use signals, like implemented on Boost.Signals or libsigc++ (the best way to go in this case).

Also, closer in syntax to what you want, new C++ specification (C++11, supported by most recent compilers) also allows for lambda functions:

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...
}

If you really want to define a new class "on the fly", it cannot be done inline, but can be done "just above":

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();
    }
};

The class can even be anonymous, but you can only create the object on stack (i.e. you can't use new on an anonymous class, and it will be deallocated upon function return):

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);
 };
七秒鱼° 2024-12-26 04:32:47

不可以。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(); 
  } 
};

No. Everything in C++ has to be defined before it can be used. In your case, since you want to override A::foo(), you have to derive a new class, and then B can instantiate that class, eg:

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(); 
  } 
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文