Почему я не могу объявить класс вне класса в Vala (ошибка: переопределение структуры)? - PullRequest
0 голосов
/ 16 декабря 2018

Пример ниже, 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;
  }
}

Однако, если я прокомментирую строки, помеченные как "текущий", и раскомментирую закомментированный код, я получу эту ошибку:

$ 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 Ответ

0 голосов
/ 16 декабря 2018

Это связано с тем, как работает GObject и его соглашениями по присвоению имен.Руководство GObject содержит более подробную информацию , поэтому я не буду вдаваться в подробности ...

Когда вы создаете объект, давайте назовем его Foo, в Vala, вВ сгенерированном C будут созданы две структуры: Foo и FooClass.Первый - это то, что люди чаще всего используют в API, и представляет собой экземпляр Foo, тогда как последний используется для хранения информации о самом классе Foo;виртуальные указатели на функции - это большая вещь.

Итак, с вашим кодом выше, сгенерированный код будет содержать Test и TestClass для внешнего класса и TestTestClass и TestTestClassClass для внутреннего класса.,Как только вы раскомментируете оставшуюся часть кода, он попытается сгенерировать TestClass и TestClassClass, первый из которых будет конфликтовать со структурой *Class для уже существующего внешнего класса.

Вы можетенемного проще воспроизвести проблему с помощью:

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

В принципе, не вызывайте класс *Class.

...