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

rtti - C++

Восстановить пароль Регистрация
 
underwaterspace
2 / 2 / 0
Регистрация: 29.01.2013
Сообщений: 47
01.08.2013, 18:14     rtti #1
Есть код:
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
// header.h
#include <stdexcept>
#include <string>
#include <typeinfo>
#include <cstdlib>
 
class Sales
{
protected:
    enum {MONTHS = 12};   
public:
    class bad_index : public std::logic_error
    {
    private:
        int bi;  
    public:
        explicit bad_index(int ix,
            const std::string & s = "Index error in Sales object\n");
        int bi_val() const {return bi;}
        virtual ~bad_index() throw() {}
    };
    explicit Sales(int yy = 0);
    Sales(int yy, const double * gr, int n);
    virtual ~Sales() { }
    int Year() const { return year; }
    virtual double operator[](int i) const;
    virtual double & operator[](int i);
private:
    double gross[MONTHS];
    int year;
};
 
class LabeledSales : public Sales
{
  public:
    class nbad_index : public Sales::bad_index
    {
    private:
        std::string lbl;
    public:
        nbad_index(const std::string & lb, int ix,
           const std::string & s = "Index error in LabeledSales object\n");
        const std::string & label_val() const {return lbl;}
        virtual ~nbad_index() throw() {}
     };
    explicit LabeledSales(const std::string & lb = "none", int yy = 0);
    LabeledSales(const std::string & lb, int yy, const double * gr, int n);
    virtual ~LabeledSales() { }
    const std::string & Label() const {return label;}
    virtual double operator[](int i) const;
    virtual double & operator[](int i);
private:
    std::string label;
};
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
60
61
62
63
64
65
66
67
68
69
70
71
72
// method.cpp
#include "header.h"
using std::string;
 
Sales::bad_index::bad_index(int ix, const string & s )
    : std::logic_error(s), bi(ix)
{
}
 
Sales::Sales(int yy)
{
    year = yy;
    for (int i = 0; i < MONTHS; ++i)
        gross[i] = 0;
}
 
Sales::Sales(int yy, const double * gr, int n)
{
    year = yy;
    int lim = (n < MONTHS)? n : MONTHS;
    int i;
    for (i = 0; i < lim; ++i)
        gross[i] = gr[i];
    // for i > n and i < MONTHS
    for ( ; i < MONTHS; ++i)
        gross[i] = 0;
}
 
double Sales::operator[](int i) const
{
    if(i < 0 || i >= MONTHS)
        throw bad_index(i);
    return gross[i];
}
 
double & Sales::operator[](int i)
{
    if(i < 0 || i >= MONTHS)
        throw bad_index(i);
    return gross[i];
}
 
LabeledSales::nbad_index::nbad_index(const string & lb, int ix,
           const string & s ) : Sales::bad_index(ix, s)
{
    lbl = lb;
}
 
LabeledSales::LabeledSales(const string & lb, int yy)
         : Sales(yy)
{
    label = lb;
}
 
LabeledSales::LabeledSales(const string & lb, int yy, const double * gr, int n)
        : Sales(yy, gr, n)
{
    label = lb;
}
 
double LabeledSales::operator[](int i) const
{    if(i < 0 || i >= MONTHS)
        throw nbad_index(Label(), i);
    return Sales::operator[](i);
}
 
double & LabeledSales::operator[](int i)
{
    if(i < 0 || i >= MONTHS)
        throw nbad_index(Label(), i);
    return Sales::operator[](i);
}
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//main.cpp
#include <iostream>
#include <typeinfo>
#include "header.h"
#include <cstdlib>
using namespace std;
int main()
{
    using std::cout;
    using std::cin;
    using std::endl;
 
    double vals1[12] =
    {
        1220, 1100, 1122, 2212, 1232, 2334,
        2884, 2393, 3302, 2922, 3002, 3544
    };
 
    double vals2[12] =
    {
        12, 11, 22, 21, 32, 34,
        28, 29, 33, 29, 32, 35
    };
 
    Sales sales1(2011, vals1, 12);
    LabeledSales sales2("Blogstar",2012, vals2, 12 );
 
    cout << "First try block:\n";
    try
    {
        int i;
        cout << "Year = " << sales1.Year() << endl;
        for (i = 0; i < 12; ++i)
        {
 
            cout << sales1[i] << ' ';
            if (i % 6 == 5)
                cout << endl;
        }
        cout << "Year = " << sales2.Year() << endl;
        cout << "Label = " << sales2.Label() << endl;
        for (i = 0; i <= 12; ++i)
        {
 
            cout << sales2[i] << ' ';
            if (i % 6 == 5)
                cout << endl;
        }
        cout << "End of try block 1.\n";
    }
    catch(Sales::bad_index & bad)
    {
        LabeledSales::nbad_index * arg;
        cout << bad.what();
        if(typeid(arg)==typeid(bad))
        {
            cout << "Company: " << bad.label_val() << endl;
        }
        cout << "bad index: " << bad.bi_val() << endl;
    }
    cout << "\nNext try block:\n";
    try
    {
        sales2[2] = 37.5;
        sales1[20] = 23345;
        cout << "End of try block 2.\n";
    }
    catch(Sales::bad_index & bad)
    {
        LabeledSales::nbad_index * arg;
        cout << bad.what();
        if(typeid(arg)==typeid(bad))
        {
            cout << "Company: " << bad.label_val() << endl;
        }
        cout << "bad index: " << bad.bi_val() << endl;
    }
    cout << "done\n";
    system("PAUSE");
    return 0;
}
Компилятор ругается(строчки 57 и 74), что 'label_val' не является методом 'Sales::bad_index', но 'LabeledSales::nbad_index' порожден от 'Sales::bad_index', что не так?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
novi4ok
549 / 502 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
01.08.2013, 18:17     rtti #2
убери из примеров все, что не относится к вопросу, тогда может кто-то найдет время глянуть. а скорее всего когда упростишь, и сам увидишь.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
01.08.2013, 18:43     rtti #3
C++
1
cout << "Company: " << bad.label_val() << endl;
bad нужно скастить к nbad_index.
underwaterspace
2 / 2 / 0
Регистрация: 29.01.2013
Сообщений: 47
01.08.2013, 19:01  [ТС]     rtti #4
ForEveR, через dynamic_cast пробовал, но выдавало, что не может из базового класса преобразоваться в производный, конечно можно явно это задать, но нужно ли? Меня больше интересно почему не пропускает nbad_index, если он порожден от bad_index
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11817 / 6796 / 769
Регистрация: 27.09.2012
Сообщений: 16,867
Записей в блоге: 2
Завершенные тесты: 1
01.08.2013, 19:40     rtti #5
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    class bad_index : public std::logic_error
    {
    private:
        int bi;  
    public:
        explicit bad_index(int ix,
            const std::string & s = "Index error in Sales object\n");
        int bi_val() const {return bi;}
        virtual ~bad_index() throw() {}
    };
//...
Sales::bad_index & bad
//...
bad.label_val()//Где у Sales::bad_index метод label_val?
Добавлено через 3 минуты
C++
1
2
3
4
        if(typeid(LabeledSales::nbad_index&)==typeid(bad))
        {
            cout << "Company: " << static_cast<LabeledSales::nbad_index&>(bad).label_val() << endl;
        }
underwaterspace
2 / 2 / 0
Регистрация: 29.01.2013
Сообщений: 47
01.08.2013, 19:44  [ТС]     rtti #6
Croessmah, разве эта часть кода должна останавливать Sales::bad_index & bad ?
C++
1
2
3
4
 if(typeid(arg)==typeid(bad))
        {
            cout << "Company: " << bad.label_val() << endl;
        }
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11817 / 6796 / 769
Регистрация: 27.09.2012
Сообщений: 16,867
Записей в блоге: 2
Завершенные тесты: 1
01.08.2013, 19:49     rtti #7
bad - это ссылка на Sales::bad_index, а у этого класса нет функции-члена с именам label_val, так что имеем ошибку компиляции
underwaterspace
2 / 2 / 0
Регистрация: 29.01.2013
Сообщений: 47
01.08.2013, 20:06  [ТС]     rtti #8
Croessmah, совсем забыл, что typeid слева принимает тип, спасибо, все заработало.
Разве bad не может ссылаться на LabeledSales::nbad_index ?
я имею в виду, что Sales::bad_index является же для LabeledSales::nbad_index базовым и, по идее, тоже должен перехватываться catch(Sales::bad_index & bad)
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11817 / 6796 / 769
Регистрация: 27.09.2012
Сообщений: 16,867
Записей в блоге: 2
Завершенные тесты: 1
01.08.2013, 20:11     rtti #9
Цитата Сообщение от underwaterspace Посмотреть сообщение
я имею в виду, что Sales::bad_index является же для LabeledSales::nbad_index базовым и, по идее, тоже должен перехватываться
Так он же перехватывается...
underwaterspace
2 / 2 / 0
Регистрация: 29.01.2013
Сообщений: 47
01.08.2013, 20:14  [ТС]     rtti #10
Croessmah, он перехватывается, но просит static_cast<LabeledSales::nbad_index&>(bad), почему?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11817 / 6796 / 769
Регистрация: 27.09.2012
Сообщений: 16,867
Записей в блоге: 2
Завершенные тесты: 1
01.08.2013, 20:21     rtti #11
Цитата Сообщение от underwaterspace Посмотреть сообщение
почему?
потому что bad - это ссылка на объект типа Sales::bad_index
И она (ссылка) понятия не имеет, что ей запихнули ссылку LabeledSales::nbad_index& и компилятор тоже не в курсе.
Для компилятора есть только тип ссылка на Sales::bad_index, а в этом классе нет метода label_val.
underwaterspace
2 / 2 / 0
Регистрация: 29.01.2013
Сообщений: 47
01.08.2013, 20:24  [ТС]     rtti #12
все стало понятно, благодарю
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.08.2013, 20:29     rtti
Еще ссылки по теме:

RTTI. Создание объекта по строковому названию класса. Delphi
C++ Как включить RTTI
Почему RTTI работает только с иерархией классов, содержащие виртуальные функции? C++

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

Или воспользуйтесь поиском по форуму:
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11817 / 6796 / 769
Регистрация: 27.09.2012
Сообщений: 16,867
Записей в блоге: 2
Завершенные тесты: 1
01.08.2013, 20:29     rtti #13
Цитата Сообщение от underwaterspace Посмотреть сообщение
bad ссылается на LabeledSales::nbad_index или Sales::bad_index ?
на LabeledSales::nbad_index, но компилятор понятия об этом не имеет. Для него это ссылка на Sales::bad_index, поэтому мы определяем, что реальный тип ссылка на LabeledSales::nbad_index
C++
1
typeid(LabeledSales::nbad_index&)==typeid(bad)
и потом кастуем Sales::bad_index& к LabeledSales::nbad_index&, тем самым, получаем уже ссылку на объект LabeledSales::nbad_index у которого есть метод label_val - для компилятора всё законно и он молчит!
Лучше даже, наверное, dynamic_cast, хотя...
Yandex
Объявления
01.08.2013, 20:29     rtti
Ответ Создать тему
Опции темы

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