Може ли обединението да съдържа обекти от клас с потребителски дефиниран конструктор?

Може ли обединението да съдържа обекти от клас с потребителски дефиниран конструктор? Когато се опитам да създам, той дава грешка, казваща „членът „c::aa“ на съюз „c“ има дефиниран от потребителя конструктор или нетривиален конструктор по подразбиране“ Това стандарт ли е или има грешка в моя код?

Кодът, който тествах, е

class a
{  
public:

  int aaa;
  a(){}

};

class b
{

public :

  long bbb;
  b() { }

};

union c
{

public :

  c()  {}

    a aa;
  b bb;  
};

person GAP    schedule 09.01.2014    source източник


Отговори (3)


Преди C++11 отговорът е "не" - union може да съдържа само типове стойности (за заемане на термин от управляван код), тоест тип, който съдържа само членове с данни.

Unions споделят своя отпечатък от паметта между всички членове. Наличието на сложни членове в обединение би довело до ситуация, при която методите, действащи върху членове на данни от един клас, биха затрили членове на данни на другия клас в обединението.

Може би това, което искате, е struct.

person Brian A. Henning    schedule 09.01.2014
comment
Благодаря за отговора. Използвах клас за учебна цел. Така че лоша практика ли е да се използват обекти от клас или това е проблем, който може да доведе до срив/двусмислено поведение? - person GAP; 09.01.2014
comment
Бих го нарекъл лоша практика. Използвайте union само когато изрично искате два обекта да споделят едно и също пространство в паметта. Девет пъти от десет почти винаги трябва да използвате struct, а не union. - person Brian A. Henning; 09.01.2014
comment
При какви обстоятелства this някога се съхранява в паметта на обект? - person Rob Kennedy; 09.01.2014
comment
Няма значение дали използвате клас или структура. Структурата може да има и конструктор. Честно казано, малко съм изненадан, че конструкторът би бил проблем, тъй като това не прави оформлението на паметта нетривиално. Мислех, че C++11 трябваше да смекчи това правило. - person shawn1874; 10.01.2014

Това е възможно след C++11 ("неограничени съюзи").

person Kerrek SB    schedule 09.01.2014
comment
Още един богат източник на насълзяващ очите код. това няма да наруши никакъв код, тъй като само облекчава съществуващо правило. Що се отнася до разрешаването на писане на чисто нов счупен софтуер, обзалагам се, че ще стане. Прекрасна нова площадка за маниаците на шаблони, без съмнение :). - person kuroi neko; 09.01.2014
comment
@kuroi - Не разбирам коментара ти. Разбира се, това няма да наруши съществуващия код. Защо? Какво ви кара да мислите, че писането на чисто нов счупен код е допустимо? - person shawn1874; 10.01.2014
comment
Искам да кажа, че момчетата от C++11 са малко по-добре, тъй като можем да го направим, нека го направим отстрани за моя вкус. Така че вече можете да посочите един привилегирован член, на когото ще бъде позволено да обърква съдържанието на всички свои братя и сестри от съюза. Без съмнение компютърните гении ще се възползват максимално от това, но понякога се чудя дали ползите ще надделеят над милионите грешки, причинени от обикновените смъртни, които неволно се скитат в тези девствени земи. Но това е само празна мисъл. Вече не си изкарвам прехраната със C++. - person kuroi neko; 10.01.2014
comment
Не, в този случай те просто отменят грешка, която никога не е трябвало да бъде част от по-ранните стандарти, както Бярн вече беше посочил. Никога не е имало основателна причина да се предотврати използването на класове с тривиални функции в съюзи. Съжалявам, но имам малък проблем да разбера защо смятате, че това е лошо. Мисля, че е фантастично. Защо да не мога да имам тривиални функции за класове/структури в обединение? Струва ми се полезно. - person shawn1874; 10.01.2014

class a
{  
public:

  int aaa;
  a(){}

};

class b
{

public :

  long bbb;
  b() { }

};

union c
{

public :

  c()  {}

    a aa;
  b bb;  
};

int main()
{
    return 0;
}

Горният код работи добре с помощта на следния онлайн компилатор. http://www.compileonline.com/compile_cpp11_online.php

Така че отговорът е да и не, в зависимост от вашия компилатор. MS VS 2010 не компилира този код, защото все още не е напълно C++11. Очевидно най-новият C++11 GCC компилатор ще го компилира добре! Според мен това е страхотно, защото тривиалният дефиниран от потребителя конструктор просто инициализира данните и не променя оформлението на паметта.

Стандартът C++ 03 гласи, че всеки клас или структура с дефиниран от потребителя конструктор не е POD. Bjarn Stroustrup написа нещо за това на началната си страница, като посочи, че това е твърде строго определение за POD срещу не-POD, тъй като дефинираните от потребителя функции не винаги причиняват нетривиално оформление на паметта. Ето защо правилото беше облекчено.

person shawn1874    schedule 09.01.2014