C ++ переопределение типов в подклассах и нарезки - PullRequest
1 голос
/ 21 марта 2011
#include <string>
#include <iostream>

class a { public: int x;};
class b : public a  {public: int x; } ;

int main()
{
    b bee;
    bee.x = 3;

    a ay = bee;
    std::cout << std::endl << ay.x << std::endl;


}

Приведенный выше код прекрасно компилируется в clang 3.0 и g ++ 4.5. Однако вывод является ненужным (то есть, не три). Поскольку компилятор, похоже, не возражает, как мне заставить код работать?

Во-вторых, если есть какой-то способ заставить вышеуказанный фрагмент / преобразование работать правильно, насколько плохо было бы, если бы я тогда сделал следующее, при условии, что для этого есть веская причина:

class c : public a { public: uint64_t x; };

Почему меня интересует эта семантика.

Причина, по которой я хочу это сделать, заключается в следующем. У меня есть две иерархии классов, где одна иерархия (родитель) объединяет объекты на том же уровне иерархии с другой (дочерней). Я использую пользовательский контейнер для агрегации. Я хочу напечатать контейнер в родительском классе (typedefs имеют одинаковое имя) и объявить контейнер с одинаковым именем на каждом уровне родительского класса.

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

Edit:

Ну вот, это должно прояснить ситуацию.

class A { int x; }; 
class B : public A {int y;};
class Ap {std::vector<A> entries;};
class Bp : Ap{std::vector<B> entries;};

Дочерний B имеет больше членов, чем дочерний класс A. Однако я не хочу представлять единый интерфейс для кода, который интересует только членов класса A.

Ответы [ 4 ]

2 голосов
/ 21 марта 2011

Невозможно сделать это, если вы непосредственно установите b::x. a::x и b::x - два разных члена, а последний скрывает первый.

Вы все еще можете получить доступ к a::x для объекта типа b с помощью static_cast<a&>(bee).x = 3, но фундаментальная проблема заключается в том, что значения a::x и b::x для объекта типа b не синхронизированы .

Если вы абстрагируете доступ к обоим x членам с помощью "свойства getter / setter", то вы можете организовать для setter в производном классе также обновление члена базового класса. Или (может быть, это более уместно?) Вы можете сделать член базового класса protected и использовать его непосредственно из производного класса, нарезая его по мере необходимости непосредственно перед возвратом из метода получения.

1 голос
/ 21 марта 2011

да! немного сложнее нет?

почему вы не используете:

class a
{
virtual void set( int value ) { x = value; }

protected :
    int x;
};

class b : public a 
{
virtual void setA( int value ) { a::x = value; }

или

virtual void setA( int value ) { b::x = value; }

или

virtual void setA( int value ) { a::x = value; b::x = value; }

protected:
    int x;
} ;

Существует два способа конструирования программного обеспечения; Один из способов - сделать его настолько простым, чтобы не было никаких недостатков, а другой - сделать его настолько сложным, чтобы не было явных недостатков. Первый способ гораздо сложнее. C.A.R.Hoare

0 голосов
/ 21 марта 2011

Может быть попробовать что-то вроде этого:

class A { int x; }; 
class B : public A {int y;};
class Ap {
public:
    void Append(A *pa)
    {
        entries.push_back(pa);
    }
    A *GetA(size_t nIndex) 
    {
        return entries.at(nIndex);
    }
private:
    std::vector<*A> entries;
};
class Bp : Ap
{ 
public:
    B *GetB(size_t nIndex) 
    {
        return dynamic_cast<B*>(GetA(nIndex));
    }
};
0 голосов
/ 21 марта 2011

Согласно ответу Джона, поскольку a :: x и b :: x являются отдельными переменными, более того, поскольку b :: x маскирует a :: x, если вы хотите получить правильную семантику, вам нужно предоставить конструктор преобразования копии , Следующий код делает свое дело.

#include <string>
#include <iostream>

class b;

class a { 
public: 
    a();
    a(const b & bee);

    int x;
};
class b : public a  {public: int x; } ;


a::a() {}
a::a(const b & bee)
{ 
        x = bee.x;
}  

int main()
{
    b bee;
    bee.x = 3;

    a ay = bee;
    std::cout << std::endl << ay.x << std::endl; 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...