Войти
ФлеймФорумПрограммирование

C++ вызов виртуального метода из конструктора

Страницы: 1 2 3 Следующая »
#0
12:29, 1 сен. 2018

Всем известно, что в C++ при вызове из коструктора виртуального метода, он будет вызван невиртуальным образом, при вызове из конструктора базового класса, будет вызыван метод текущего базового класса, а не дочернего. Но во многих других языках сделано по другому. И допустим нужно мигрировать код из другого языка, нaпример java:

public class HelloWorld
{
  public static void main(String[] args)
  {
    TestDerived test = new TestDerived();
    System.out.print(test.someProp); // —> Derived prop
  }
}

public class TestBase
{
  public String someProp;
  public TestBase()
  {
    initializeSomeProp();
  }
  protected void initializeSomeProp()
  {
    someProp = "Base prop";
  }
}

public class TestDerived extends TestBase
{
  protected void initializeSomeProp()
  {
    someProp = "Derived prop";
  }
}

Каким образом это лучше переписать на С++? В голову приходит только всю инициализацию вынести в отдельный метод init(), и вызывать его уже отдельно явно, вне конструктора. Но это как не очень. Все таки инициализация логично должна делаться в конструкторе.


#1
13:03, 1 сен. 2018

А как это в Жабе работает? При передача функции дочернего класса я смоу читать неинициализированные поля?

#2
13:08, 1 сен. 2018

Panzerschrek[CN]
В Java все методы по умолчанию - виртуальные и их можно перегрузить. Следовательно их можно использовать из конструктора как обычные методы. Но если метод был переопределен в дочернем классе то все нормальные IDE выводят предупреждение, поскольку можно случайно поломать программу.

#3
13:13, 1 сен. 2018

Конструктор базы вызовется такой, какой он есть, в любой случае. Можешь добавить ему параметры.

#4
13:14, 1 сен. 2018

ud1
> только всю инициализацию вынести в отдельный метод init()
initializeSomeProp() же : )
уже всё вынесено, хотя "это как не очень"

#5
13:22, 1 сен. 2018

Panzerschrek[CN]
> я смоу читать неинициализированные поля?
Походу да:

+ Показать
#6
13:24, 1 сен. 2018

> Все таки инициализация логично должна делаться в конструкторе.
Так и сделай) Просто someProp должен быть аргументом конструктора.

#7
13:29, 1 сен. 2018

Try
> someProp должен быть аргументом конструктора.
А если там сложный зависимый от других переменных код?

Constructor() {
  this->prop1 = createProp1();
  this->prop2 = virtualCreateProp2(prop1);
}
#8
13:34, 1 сен. 2018

Panzerschrek[CN]
> А как это в Жабе работает? При передача функции дочернего класса я смоу читать
> неинициализированные поля?
В джаве поля по дефолту инициализируются ссылочные - null, примитивные - 0, буловые - false.

monobogdan
> то все нормальные IDE выводят предупреждение, поскольку можно случайно поломать
> программу.
скриншот предупреждения покажешь?

ud1
> Каким образом это лучше переписать на С++?
никак, с++ слишком примитивный язык, на него нельзя перенести код с богоподобной джавы
#9
13:42, 1 сен. 2018

ud1
если тебя не пугает оверхед (а в яве он точно никого не пугает)
http://rextester.com/HAQK74360

З.Ы. впрочем виртуальность тут как собаке пятая нога

#10
13:59, 1 сен. 2018

Sh.Tac.
У тебя метод будет два раза будет вызываться. В общем надо видимо фунцию в конструктор передавать

#include <iostream>
#include <string>
#include <functional>
using namespace std::placeholders;

struct Base {
    std::string prop1, prop2;

    Base(std::function<std::string (std::string)> prop2Provider) {
        prop1 = "Prop1";
        prop2 = prop2Provider(prop1);
    }
};

struct Derived: Base {
    Derived(): Base(std::bind(&Derived::defaultProp2Provider, this, _1)) {
    }

    std::string defaultProp2Provider(std::string v) {
        return v + "derived";
    }

};

int main() {
    Derived d;
    std::cout << d.prop2 << std::endl;

    return 0;
}
#11
14:07, 1 сен. 2018

ud1
> У тебя метод будет два раза будет вызываться
это же хорошо : )

в данном конкретном случае, в яве пришлось бы копипастить всё что было в базовом в каждый дочерний, а тут можно "элегантно" перебивать только то что нужно поменять

#12
14:08, 1 сен. 2018

Sh.Tac.
> в яве пришлось бы копипастить всё что было в базовом в каждый дочерний
super.methodName();

#13
14:25, 1 сен. 2018

Mephistopheles
> super.methodName();
методы вообще не нужны, конструктор сам себе метод и просто инициализирует поля

#14
14:35, 1 сен. 2018

ud1
> А если там сложный зависимый от других переменных код?
>
> Constructor() {
> this->prop1 = createProp1();
> this->prop2 = virtualCreateProp2(prop1);
> }
Больше аргументов)

Constructor(int prop1,float prop2=createProp2(prop1)):prop1(prop1),prop2(prop2){}
> никак, с++ слишком примитивный язык, на него нельзя перенести код с богоподобной джавы
обычно достаточно отрефакторить код до состояния "не лапша"
Страницы: 1 2 3 Следующая »
ФлеймФорумПрограммирование

Тема в архиве.