Форум программистов, компьютерный форум CyberForum.ru

Унаследоваться от базового класса и переопределить часть его данных - C++

Восстановить пароль Регистрация
 
 
icpu
 Аватар для icpu
276 / 181 / 36
Регистрация: 10.03.2011
Сообщений: 863
Записей в блоге: 2
06.08.2014, 18:36     Унаследоваться от базового класса и переопределить часть его данных #1
Есть базовый класс с некоторыми (protected) данными, в том числе объявленными const, и (public) виртуальными функциями. Требуется унаследоваться от него и переопределить часть этих данных.

Проблема - const члены класса. Как можно переопределить эти члены так, чтобы изменения подхватывали базовые методы?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.08.2014, 18:36     Унаследоваться от базового класса и переопределить часть его данных
Посмотрите здесь:

C++ Конструктор базового класса
Как переопределить конструктор класса C++
C++ Использование перегруженного оператора ввода/вывода в поток базового класса для объекта производного класса
Вызов метода базового класса из класса-потомка C++
C++ Как построить экземпляр дочернего класса на основе готового экземпляра базового класса?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
CyberSolver
 Аватар для CyberSolver
101 / 74 / 17
Регистрация: 23.07.2014
Сообщений: 686
Записей в блоге: 1
06.08.2014, 18:38     Унаследоваться от базового класса и переопределить часть его данных #2
icpu, напишите код, который вы хотите заставить работать.
icpu
 Аватар для icpu
276 / 181 / 36
Регистрация: 10.03.2011
Сообщений: 863
Записей в блоге: 2
06.08.2014, 19:13  [ТС]     Унаследоваться от базового класса и переопределить часть его данных #3
Да любой. Например
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//base.h
class base {
protected:
   static const float a;
   static const float b;
public:
   base();
   void foo();
};
 
//base.cpp
const float base::a = 3.;
const float base::b = 3.;
base::base(){};
void base::foo(){printf("base:%f,%f\n",a,b);};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//delivered.h
class delivered: 
   virtual public base{
protected:
   static const float b;
public:
   delivered();
   void bar();
};
 
//delivered.cpp
const float delivered::b = 3.1415926535;
delivered::delivered(){};
void delivered::bar(){printf("delivered:%f,%f\n",a,b);};
C++
1
2
3
4
5
6
void main(){
base b;
delivered d;
b.foo();
d.foo();
d.bar();}
C++
1
2
3
base:3,3
base:3,3
delivered:3,3.1415926535
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
06.08.2014, 19:33     Унаследоваться от базового класса и переопределить часть его данных #4
Цитата Сообщение от icpu Посмотреть сообщение
Как можно переопределить эти члены так, чтобы изменения подхватывали базовые методы?
Это не переопределение, а сокрытие. Т.е это разные переменные. В твоем примере по base::b будет доступна переменная со значением 3 из базового класса.
Есть пара извращений, которые можно предложить, чтобы решить вопрос примерно так, как ты хочешь. Но лучше расскажи какую задачу решаешь, наверняка есть способ прямее и лучше, чем вот это.
RussBear
 Аватар для RussBear
1 / 1 / 1
Регистрация: 06.08.2014
Сообщений: 77
06.08.2014, 19:45     Унаследоваться от базового класса и переопределить часть его данных #5
icpu, я стесняюсь спросить, а Вы этот пример сами придумали? И для чего Вам это нужно.
Цитата Сообщение от icpu Посмотреть сообщение
protected:
* *static const float a;
* *static const float b;
Это вообще что? Я сильно сомневаюсь что компилятор пропустит неинициализированную константу. Вроде как ее при объявлении нужно инициализировать.
Цитата Сообщение от icpu Посмотреть сообщение
void delivered::bar(){printf("delivered:%f,%f\n",a,b);};
И определитесь пожалуйста с языком: для чего в С++ использовать чисто сишные функции?
чем Вас не устраивает
C++
1
std::cout << "чего то там " << a << b << "\n";
DrOffset
06.08.2014, 19:53
  #6

Не по теме:

Цитата Сообщение от RussBear Посмотреть сообщение
И определитесь пожалуйста с языком: для чего в С++ использовать чисто сишные функции?
Да ладно к printf-то придираться
Вот если например написать
C++
1
2
#include <cstdio>
std::printf("%s", ".......");
то это будет уже легально С++.

RussBear
06.08.2014, 20:01
  #7

Не по теме:

DrOffset, ну согласитесь что особого смысла в использовании printf() нет, но это к сути вопроса отношения не имеет, я вот все пытаюсь понять чего автор хочет добиться. Кто бы просветил...
Если это сделано для изучения полиморфизма, то это очень неудачный пример

DrOffset
06.08.2014, 20:11
  #8

Не по теме:

Цитата Сообщение от RussBear Посмотреть сообщение
ну согласитесь что особого смысла в использовании printf() нет
Учитывая, что это наверняка накиданный прямо в браузере пример, то смысла обращать на это внимания нет. Да и printf - на самом деле отличное средство, быстрое, форматирование, опять же, удобное. Только вот небезопасное с точки зрения типов. И это его единственный недостаток по большому счету. Не то, чтобы я сейчас говорю, что нужно смешивать С и С++ - нет, но и однозначно говорить, что функциям такого рода нет места в С++ коде никогда, я бы не стал.

icpu
 Аватар для icpu
276 / 181 / 36
Регистрация: 10.03.2011
Сообщений: 863
Записей в блоге: 2
06.08.2014, 20:11  [ТС]     Унаследоваться от базового класса и переопределить часть его данных #9
DrOffset, я знаю, что это сокрытие. И что доступ к базовым членам осуществляется через, например, base::a.

В том то и проблема, что мне дан уже готовый класс с собраной в либу реализацией. Класс - решатель одной узкой задачи, веса решателя вшиты в виде статических констант. Переписывать всю реализацию из-за трёх констант и пяти функций просто лень. Я уже, даже, об изменении кода библиотеки подумывал, но опять же...
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
06.08.2014, 20:18     Унаследоваться от базового класса и переопределить часть его данных #10
Цитата Сообщение от icpu Посмотреть сообщение
В том то и проблема, что мне дан уже готовый класс с собраной в либу реализацией. Класс - решатель одной узкой задачи, веса решателя вшиты в виде статических констант.
То есть нужно подменить реализацию констант в базовом классе, чтобы, опять же, функции базового класса, смогли использовать эти другие значения констант в своих расчетах, но сделать это только для конкретного наследника? Если так, то я скажу, что без хаков это невозможно.

Добавлено через 1 минуту
Причем я даже больше скажу. Компилятор внутри либы мог вполне встроить эти значения по месту во всех используемых местах и тогда даже с хаками ничего сделать нельзя будет.
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
06.08.2014, 20:19     Унаследоваться от базового класса и переопределить часть его данных #11
Лучше проведи рефакторинг библиотеки, это чуть больше времени. Зато потом тебе спасибо скажут.
icpu
 Аватар для icpu
276 / 181 / 36
Регистрация: 10.03.2011
Сообщений: 863
Записей в блоге: 2
06.08.2014, 20:28  [ТС]     Унаследоваться от базового класса и переопределить часть его данных #12
DrOffset, код либы бы дали сначала. В общем, ясно, дело труба.

RussBear, то-то и оно, что я не бездумно писал.
инциализация константного члена класса
C++
1
2
3
4
5
6
7
8
9
//h
class c{
const float a;
/*...*/};
 
//cpp
c::c():
   a(3.14)
{/*...*/};
инциализация статического члена класса
C++
1
2
3
4
5
6
7
8
//h
class c{
static float a;
/*...*/};
 
//cpp
float c::a = 3.14;
{/*...*/};
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
06.08.2014, 20:38     Унаследоваться от базового класса и переопределить часть его данных #13
Цитата Сообщение от icpu Посмотреть сообщение
DrOffset, код либы бы дали сначала
Кривой дизайн класса в либе налицо. Коэффициента a и b должны были быть псевдоконстантными значениями, с возможностью передачи кастомных значений через параметры конструктора:
C++
1
2
3
4
5
6
7
class Base
{
    const float a;
    const float b;
public:
    Base(float a = 3, float b = 3) : a(a), b(b) {}
};
Тогда для наследника можно было бы задать свои коэффициенты и все бы разрешилось.
А в этом случае со статическими константами, даю 99.9%, что компилятор их встроил прямо в вызовы во всех алгоритмах либы. Формально (если они в привате), он мог вообще не выделять память под них. Так что, действительно, труба.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
06.08.2014, 21:54     Унаследоваться от базового класса и переопределить часть его данных #14
Цитата Сообщение от DrOffset Посмотреть сообщение
Формально (если они в привате), он мог вообще не выделять память под них.
А причем тут private? Может где-то адрес берется от этой переменной, тогда память нужна по-любому.
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
06.08.2014, 22:28     Унаследоваться от базового класса и переопределить часть его данных #15
Цитата Сообщение от Tulosba Посмотреть сообщение
А причем тут private? Может где-то адрес берется от этой переменной, тогда память нужна по-любому.
А я где-то утверждал, что он 100% ее выкинул? Там как бы слово "мог" использовалось.
icpu
 Аватар для icpu
276 / 181 / 36
Регистрация: 10.03.2011
Сообщений: 863
Записей в блоге: 2
06.08.2014, 22:31  [ТС]     Унаследоваться от базового класса и переопределить часть его данных #16
DrOffset, чисто для академических познаний, как можно сделать константный статический объект, переопределяемый потомками? Псевдоконстантный с параметрами по умолчанию - это понятно. А вот статик конст? А то мало ли, вдруг герой-имбицил решит сменить, к примеру, имя раздела в базе данных посреди выполнения программы.
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
06.08.2014, 22:33     Унаследоваться от базового класса и переопределить часть его данных #17
Цитата Сообщение от Tulosba Посмотреть сообщение
А причем тут private?
А приват тут очень даже причем.
Если константа в private, адрес ее нигде не берется, friend функций нет, то компилятор вполне может не размещать ее в памяти, а просто подставить значение во всех вычислениях. Вот в случае с public такое уже не прокатит, т.к. компилятор не вправе делать предположение о том, что адрес никогда не будет взят.

Добавлено через 2 минуты
Цитата Сообщение от icpu Посмотреть сообщение
Псевдоконстантный с параметрами по умолчанию - это понятно. А вот статик конст? А то мало ли, вдруг герой-имбицил решит сменить, к примеру, имя раздела в базе данных посреди выполнения программы.
static - это считай глобальный объект. Так что именно переопределить не получится
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
06.08.2014, 22:36     Унаследоваться от базового класса и переопределить часть его данных #18
DrOffset, я не про выкидывание как таковое, а про private. Будь оно public или protected разве это бы что-то поменяло?

Добавлено через 2 минуты
Цитата Сообщение от DrOffset Посмотреть сообщение
компилятор не вправе делать предположение о том, что адрес никогда не будет взят.
Для интегральных типов можно было форсировать всё это инициализацией в классе. Тогда взятие адреса уже будет ошибкой этапа компиляции.
DrOffset
6426 / 3800 / 880
Регистрация: 30.01.2014
Сообщений: 6,594
06.08.2014, 22:44     Унаследоваться от базового класса и переопределить часть его данных #19
Цитата Сообщение от Tulosba Посмотреть сообщение
Будь оно public или protected разве это бы что-то поменяло?
Конечно поменяло бы. У него ведь библиотека.
Предположим, что использование статической константы А имеется только в одной единице трансляции. В заголовочном файле соответственно объявление класса. Константа в private, friend-функций, определенных в других единицах трансляции нет. Означает, что раз адрес не был взят в той единственной единице трансляции, где используется А, значит он не будет взят более нигде, т.к. переменная в private. (Я вот точно такое же поведение наблюдал на примере функций класса, которые компилятор выкидывал, если они были в private и не вызывались более нигде, кроме как в одной единице трансляции (где определен класс)). Но у нас библиотека, поэтому protected и public не позволят делать эту оптимизацию, т.к. неизвестно будет ли брать наследник или внешний пользователь адрес переменной или нет.

Добавлено через 2 минуты
Цитата Сообщение от Tulosba Посмотреть сообщение
Для интегральных типов можно было форсировать всё это инициализацией в классе. Тогда взятие адреса уже будет ошибкой этапа компиляции.
Это ты разговор в сторону уводишь
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.08.2014, 09:57     Унаследоваться от базового класса и переопределить часть его данных
Еще ссылки по теме:

C++ Создать массив указателей базового класса и присвоить ему адреса каждого из екземпляров класса
Вызов конструктора базового класса из класса-наследника C++
Конструктор базового класса C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
CyberSolver
 Аватар для CyberSolver
101 / 74 / 17
Регистрация: 23.07.2014
Сообщений: 686
Записей в блоге: 1
07.08.2014, 09:57     Унаследоваться от базового класса и переопределить часть его данных #20
icpu, я в упор не понимаю вашей проблемы. Зачем вам именно наследоваться от вашого вшитого в либу класса? Просто использовать нельзя?
Yandex
Объявления
07.08.2014, 09:57     Унаследоваться от базового класса и переопределить часть его данных
Ответ Создать тему
Опции темы

Текущее время: 16:19. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru