代码之家  ›  专栏  ›  技术社区  ›  sdaau

为什么我不能在vala中声明类之外的类(错误:结构的重定义)?

  •  0
  • sdaau  · 技术社区  · 6 年前

    下面的例子, test4.vala ,编译并运行:

    //// compile with: valac test4.vala
    
    //~ public class TestClass : GLib.Object { // error: redefinition of ‘struct _TestClass’
      //~ public int x = 0;
      //~ public int y = 0;
      //~ public int z = 0;
    //~ }
    
    public Test App;
    
    public class Test : GLib.Object {
    
      public class TestClass : GLib.Object {  //current
        public int x = 0;                     //current
        public int y = 0;                     //current
        public int z = 0;                     //current
      }                                       //current
    
      public TestClass mytc;
      public void SetVars() {
        mytc = new TestClass();
        stdout.printf("SetVars called, %p\n", mytc);
      }
    
      public Test(string[] args){
        stdout.printf("Test() ctor: ok\n");
        stdout.flush();
      }
    
      public static int main (string[] args) {
        App = new Test(args);
        App.SetVars();
        stdout.printf("main called\n");
        return 0;
      }
    }
    

    但是,如果我对标记为“current”的行进行注释,并取消注释注释代码,则会得到以下错误:

    $ valac test4.vala && ./test4 
    /tmp/test4.vala.c:64:8: error: redefinition of ‘struct _TestClass’
     struct _TestClass {
            ^~~~~~~~~~
    /tmp/test4.vala.c:20:16: note: originally defined here
     typedef struct _TestClass TestClass;
                    ^~~~~~~~~~
    error: cc exited with status 256
    Compilation failed: 1 error(s), 0 warning(s)
    

    我仍然试图摸索瓦拉,但这让我有点困惑-为什么我不能在一个携带 main 和它在同一个层次上-但是我必须在主应用程序类中“包含”这个其他类?

    1 回复  |  直到 6 年前
        1
  •  4
  •   nemequ    6 年前

    它与gobject的工作方式及其命名约定有关。Gobject手册 more details 所以我不会深入到这里。

    当你创建一个对象时,让我们称之为 Foo ,在vala中,在生成的c中,将创建两个结构: FooClass . 前者是人们将主要在API中使用的,它代表了 ,而后者用于保存有关 类本身;虚拟函数指针是最重要的。

    因此,使用上面的代码,生成的代码将包含 Test TestClass 对于外部阶级,以及 TestTestClass TestTestClassClass 对于内部阶级。一旦取消对其余代码的注释,它将尝试生成 测试类 TestClassClass ,前者将与 *Class 已存在的外部类的结构。

    您可以通过以下方式更轻松地再现问题:

    public class Test : GLib.Object { }
    public class TestClass : GLib.Object { }
    

    基本上,不要叫班 *类 .