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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 27, средняя оценка - 5.00
LineStown
66 / 66 / 3
Регистрация: 04.08.2010
Сообщений: 420
Завершенные тесты: 1
#1

Не вызывается конструктор базового класса - C++

04.08.2010, 17:35. Просмотров 3540. Ответов 44
Метки нет (Все метки)

Доброго времени суток.
У меня проблема:в производном классе не вызывается конструктор базового класса.
Думаю описывать класс не стоит, т.к. он простейший.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<iostream>
#include<cstring>
using namespace std;
class String
{
protected:
    enum {SZ=80};
    char str[SZ];
public:
    String()
    {
        str[0]='\0';
    }
    String(char s[])
    {
        strcpy(str,s);
    }
    void display()const
    {
        cout << str << endl;
    }
};
class Pstring:public String
{
public:
    Pstring(char s[]);
};
Pstring::Pstring(char s[])
{
    if(strlen(s)>SZ-1)
    {
        for(int j=0;j<SZ;j++)
        str[j]=s[j];
        str[SZ-1]='\0';
    }
    else
        String(s);  //Вызов конструктора с параметром не проиходит. 
                                     //Результат пустая строка
};
int main()
{
    Pstring g="Qwertythdththdhdhtdh";
    g.display();
    return 0;
}
Поделитесь мыслью, что не так.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.08.2010, 17:35
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Не вызывается конструктор базового класса (C++):

Не вызывается нужный конструктор базового класса - C++
Здравствуйте. Я пока в процессе изучения С++. Имеется следующая структура классов: Базовый: Person, расширяющие его: Student и...

При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О - C++
Вот такой кодclass A { public: A(){} virtual ~A(){} }; class C { public:

Наследование: почему вызывается метод базового класса, а не производного? - C++
Всем привет, такой вопрос, почему вызывается в данном коде метод базового класса, а не производного (без указания ключевого слова virtual...

Конструктор базового класса - C++
Привет, друзья, есть, к примеру, такие классы: class Base { public: int x; Base() { } };

Конструктор базового класса - C++
Такая проблема: имеется конструктор базового класса ErrorDataErrorData(ErrorCod cod, bool isFatal);, где ErrorCod вот такая...

Будет ли утрачена память, когда конструктор копирования вызывается для уже существующего объекта класса? - C++
class A { char * v; A(); ~A(); A(const A &amp;obj); } ///////////////////// A::A() {

44
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
12.07.2012, 23:53 #31
Цитата Сообщение от LineStown Посмотреть сообщение
String(s);
вы например тут создаете временный объект, а не вызываете конструктор базового класса
это вам не джава

прочтите, что вам написал CyBOSSeR

Добавлено через 44 секунды
пардон, я слоупок))
0
VerDicT
0 / 0 / 0
Регистрация: 20.12.2011
Сообщений: 5
13.07.2012, 00:35 #32
ну а конструктор производного класса можно вызвать из другого конструктора (того же класса)?
0
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
13.07.2012, 00:49 #33
VerDicT, нет!
в некоторых случаях это было бы удобно, но в с++ есть заданный стандартом порядок вызовов конструкторов предков и полей
в чем смысл противоречия:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A {
public:
  A() { /* ... */ }
protected:
  int a;
};
 
class B {
public:
  B() {
    a = 100500; // Если бы конструктор можно было бы вызывать из произвольного места
    A();            // то мы могли бы иметь доступ к полям предка до его инициализации
  }
};
Поэтому и есть список инициализации с ограничениями на порядок

к слову в жабе можно по ходу дела вызывать конструктор предка (и не вызывать), но там от этого анархия (я считаю из своего не очень большого опыта писания на жабе)
0
alsav22
5425 / 4820 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
13.07.2012, 05:38 #34
Почитал, посмотрел что компилятор пишет и выскажу своё мнение. Мне кажется, что вот это:
C++
1
String(s);
и вот это:
C++
1
String s;
есть одно и тоже (скобки здесь не играют никакой роли): создание локольного объекта класса String конструктором по умолчанию.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
Pstring::Pstring(char *s)
{
    if(strlen(s) > SZ - 1)
    {
        for(int j = 0; j < SZ; j++)
        str[j] = s[j];
        str[SZ-1] = '\0';
    }
    else
    {
       String (s); // создание локального объекта s конструктором по умолчанию.
    } 
}
При этом в str записывается пустая строка.
И когда ТС пишет, в конструкторе производного класса:
C++
1
 String (s);
, то это всё равно, что написать
C++
1
String s;
Поэтому s в String (s); не имеет никакого отношения к s, в парметрах конструктора Pstring. Для ясности можно так написать:
C++
1
2
String(s);
s.display();
Невозможно в теле конструктора производного класса создать объект базового класса, который будет являтся частью объекта производного класса. Создаётся временный объект, который перестаёт существовать после выхода из конструктора производного класса. Возможно только ДО вхождения в тело конструктора (через список инициализаторов). Поэтому, в данном примере создаётся, конструктором по умолчанию, просто временный объект s базового класса, который не является частью никакого объекта производного класса. А через g.display(); выводится поле str объекта базового класса, который создан, конструктором по умолчанию, при создании объекта g производного класса и является его частью. Если так написано:
C++
1
String(s).display();
, то будет создан временный, неименованный объект базового класса (уже не конструктором по умолчанию), поле str которого будет проинициализированно значением параметра s и выведено на консоль, после чего этот объект станет недоступен (исчезнет).

Добавлено через 8 минут
Цитата Сообщение от LineStown Посмотреть сообщение
CyBOSSeR, Спасибо, я понял, что только список инициализации вызовет конструктор.
Тему можно закрывать
Не только. Если нужно явно, то через список. Если в списке не задан, то будет вызываться неявно конструктор по умолчанию при создании каждого объекта производного класса.

Добавлено через 39 минут
Цитата Сообщение от alex_x_x Посмотреть сообщение
B() {
a = 100500; // Если бы конструктор можно было бы вызывать из произвольного места
A(); // то мы могли бы иметь доступ к полям предка до его инициализации
Можно вызывать из произвольного места, но созданный объкет-предок, не будет иметь никакого отношения к тому объекту-наследнику из которого был вызван конструктор. А наследники имеют доступ к полям только тех предков, которые являются их частью.
0
salam
165 / 146 / 14
Регистрация: 10.07.2012
Сообщений: 738
13.07.2012, 06:56 #35
Цитата Сообщение от LineStown Посмотреть сообщение
enum {SZ=80};
не первый раз такой код вижу... объясните, будьте любезны, в чем смысл писать такую...забавную штуковину...
0
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
13.07.2012, 07:47 #36
Цитата Сообщение от alsav22 Посмотреть сообщение
Можно вызывать из произвольного места, но созданный объкет-предок, не будет иметь никакого отношения к тому объекту-наследнику из которого был вызван конструктор. А наследники имеют доступ к полям только тех предков, которые являются их частью.
с цпп даже нет такого синтаксиса - это была фантазия
0
alsav22
5425 / 4820 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
13.07.2012, 12:10 #37
Цитата Сообщение от alex_x_x Посмотреть сообщение
с цпп даже нет такого синтаксиса - это была фантазия
Я не о синтаксисе. Код случайно в цитату попал. Я о сути: можно или нельзя вызвать из произвольного места и, если мжно, то что мы имеем.

Добавлено через 32 минуты
Сообщение от LineStown
enum {SZ=80};
не первый раз такой код вижу... объясните, будьте любезны, в чем смысл писать такую...забавную штуковину...
Один из способов объявления констант в классе. Дело в том, что сделать в объявлении класса так:
C++
1
2
3
4
5
6
7
class String
{
    protected:
        const int SZ = 80;
        char str[SZ];
    public:
....................
не получится, потому что тогда, под переменную SZ, должна быть выделена память, а память под переменные класса выделяется при создании объекта класса, а не при объявлении класса. Если же задано перечисление
C++
1
enum {SZ=80};
, то это всего лишь символическое имя , которое компилятор использует в пределах этого класса и заменяет на 80. Ещё одни способ объявления констант в классах:
C++
1
static const int SZ = 80;
. В этом случае, как и для всех других статических переменных класса, память под SZ в объектах класса тоже не выделяется.
0
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
13.07.2012, 12:23 #38
Цитата Сообщение от alsav22 Посмотреть сообщение
не получится, потому что тогда, под переменную SZ, должна быть выделена память, а память под переменные класса выделяется при создании объекта класса, а не при объявлении класса. Если же задано перечисление
константа по сути может не принадлежать объекту физически, так же как и статические методы не принадлежат объектам
здесь нет никакой магии, просто язык кривой
0
alsav22
5425 / 4820 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
13.07.2012, 13:13 #39
Цитата Сообщение от alex_x_x Посмотреть сообщение
константа по сути может не принадлежать объекту физически,
Да. Просто не принадлежит, поэтому так и объявляется. Храниться отдельно от объектов. Доступна для всех объектов этого класса, так же как и методы класса.
0
VerDicT
0 / 0 / 0
Регистрация: 20.12.2011
Сообщений: 5
13.07.2012, 22:48 #40
Я напомню, что главной идеей этого упражнения было многократное использование кода вместо перепечатывания.
Я решил этот вопрос так (строки 11-14, 22, 49):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <string.h>
 
using namespace std;
 
class String
{
    protected:
        enum {SZ = 80};
        char str[SZ];
        void constructor(char s[])
        {
            strcpy(str, s);
        }
    public:
        String()
        {
            str[0] = '\x0';
        }
        String(char s[])
        {
            constructor(s);
        }
        void display() const
        {
            cout << str;
        }
        operator char*()
        {
            return str;
        }
};
 
class Pstring: public String
{
    public:
        Pstring(char s[])
        {
            if (strlen(s) >= SZ)
            {
                for (int i = 0; i < SZ - 1; i++)
                {
                    str[i] = s[i];
                }
                str[SZ - 1] = '\x0';
            }
            else
            {
                String::constructor(s);
            }
        }
};
 
int main ()
{
    Pstring s1 = "0123456789";
    s1.display();
    return 0;
}
0
alsav22
5425 / 4820 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
14.07.2012, 12:00 #41
В 49 строке можно и просто:
C++
1
constructor(s);
Добавлено через 25 минут
И, если не трудно, поясните эту конструкцию:
C++
1
2
3
4
operator char*()
        {
            return str;
        }
Она здесь зачем?
0
ForEveR
В астрале
Эксперт С++
7979 / 4738 / 321
Регистрация: 24.06.2010
Сообщений: 10,543
Завершенные тесты: 3
14.07.2012, 12:03 #42
alsav22, Оператор неявного преобразования к типу char*, рекомендуется использовать крайне аккуратно и лучше использовать либо именованные функции преобразования, либо explicit операторы преобразования типа (С++11).
0
alsav22
5425 / 4820 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
14.07.2012, 12:33 #43
Цитата Сообщение от ForEveR Посмотреть сообщение
alsav22, Оператор неявного преобразования к типу char*, рекомендуется использовать крайне аккуратно и лучше использовать либо именованные функции преобразования, либо explicit операторы преобразования типа (С++11).
Я не понял, зачем задано явное преобразование в этом коде? Где здесь объект приводится к указателю на char (может ТС считает, что здесь: Pstring s1 = "0123456789";)? Или что, его всегда нужно задавать?
0
VerDicT
0 / 0 / 0
Регистрация: 20.12.2011
Сообщений: 5
14.07.2012, 18:27 #44
Цитата Сообщение от alsav22 Посмотреть сообщение
Я не понял, зачем задано явное преобразование в этом коде? Где здесь объект приводится к указателю на char (может ТС считает, что здесь: Pstring s1 = "0123456789";)? Или что, его всегда нужно задавать?
Это упражнение Сказано: "возьмите этот класс..." Вот я и взял
0
alsav22
5425 / 4820 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
14.07.2012, 18:38 #45
Цитата Сообщение от VerDicT Посмотреть сообщение
Это упражнение Сказано: "возьмите этот класс..." Вот я и взял
Понял.
0
14.07.2012, 18:38
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.07.2012, 18:38
Привет! Вот еще темы с ответами:

this(Всегда ли вызывается конструктор при не явной передачи объекта в конструктор) - C++
class Test { int i; public: void test(int i) { this -&gt; i = i; } }; Конструктор Test::Test всегда вызывается...

Конструктор класса не видит конструктор по умолчанию другого класса - C++
Ошибка, естественно, в Classes.cpp, в строке 20. Ругается, что у класса TailNode нет конструктора по умолчанию, хотя он там, конечно, есть....

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

Конструктор вызывается 2 раза - C++
Помогите пожалуйста найти ошибку. Конструктор вызывается 2 раза. #include &lt;iostream&gt; #include &lt;stdio.h&gt; #include &lt;fstream&gt; using...


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

Или воспользуйтесь поиском по форуму:
45
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru