Jump to content

Visual C++ 2010 Empty Base Issue

- - - - -

  • Please log in to reply
6 replies to this topic

#1
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
The following code

#include <cstdio>

class E1
{
public:
  void ReportE1()
  {
        std::printf("In E1, this is %p\n", this);
  }
};

class E2
{
public:
  void ReportE2()
  {
        std::printf("In E2, this is %p\n", this);
  }
};


class E3
{
public:
  void ReportE3()
  {
        std::printf("In E3, this is %p\n", this);
  }
};



class D: public E1, public E2, public E3
{
};


int main()
{
        D d;
        d.ReportE1();
        d.ReportE2();
        d.ReportE3();
}


Reports the same this pointer values if compiled using G++;

However, when I compile it using visual C++ 2010 express, the values reported increment by 1, say 10000,10001,10002. I believe this is not standard compliant, or should I say this was not standard compliant. Is there any way I can set a swith so that it behaves exactly same as in G++?

Thanks!

#2
Ancient Dragon

Ancient Dragon

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 400 posts
That main() you posted is wrong. It should be as shown below. With class D the "this" pointer will be the same because there is only one instantiation of the class. D juist mearly inherits the attributes from E1, E2 and E3.

Here is what I get with VC++ 2010 Express

Quote

In E1, this is 0026F817
In E2, this is 0026F80B
In E3, this is 0026F7FF
Press any key to continue . . .
And here is the complete program

int main()

{

	E1 e1;

	E2 e2;

	E3 e3;

	e1.ReportE1();

	e2.ReportE2();

	e3.ReportE3();

	return 0;

}



Visit Grandpa's Forums, a social networking forum, with family-oriented arcade games, blogs, discussion forums, and photo albums.

#3
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
No, it's not. the main function will return 0 by default, this is part of the standard. Comment the line you added, the program will compile just fine, unless you're using some really old compiler.


BTW, you didn't answer my question. You might not read enough to understand it at all.

BY standard, if a class contains an empty object, that empty object is expected to occupy at least char's space, eg:

#include <cstdio>

class E1
{
public:
  void ReportE1()
  {
        std::printf("In E1, this is %p\n", this);
  }
};

class E2
{
public:
  void ReportE2()
  {
        std::printf("In E2, this is %p\n", this);
  }
};


class E3
{
public:
  void ReportE3()
  {
           std::printf("In E3, this is %p\n", this);
  }
};



class D
{
public:
       E1 e1;
       E2 e2;
       E3 e3;
};


int main()
{
           D d;
           d.e1.ReportE1();
           d.e2.ReportE2();
           d.e3ReportE3();
}


The standard also says, when an empty class is used as base class, it will occupy no space.

I actually would like it occupies no space at all in both cases, the old Borland C++ has options so that you can have empty members.


Anyway, there should be a switch/setting for VC++ to make empty base class occupy no room. Problem is, how?

Edited by Lance, 30 April 2010 - 03:45 AM.
Formatting


#4
Ancient Dragon

Ancient Dragon

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 400 posts

Lance said:

No, it's not. the main function will return 0 by default, this is part of the standard.

I wasn't talking about the return statement.


Quote

The standard also says, when an empty class is used as base class, it will occupy no space.

Those are not empty classes. Each one has a method.
Visit Grandpa's Forums, a social networking forum, with family-oriented arcade games, blogs, discussion forums, and photo albums.

#5
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
:)

Did you actually try my code in g++ and some other compiler?


A class that:
1. has no virtual method;
2. has no non-empty base class;
3. has no non-static memeber variables

is an Empty class. I might miss some points, but basically that's it. 10,000 non-virtual member functions would not be able to disqualify a class as Empty.

#6
Ancient Dragon

Ancient Dragon

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 400 posts
I compiled with Code::Blocks w/MinGW compiler and it produced the same address for each of the three classes. I fiddled around with VC++ options and was unable to make it duplicate that same output.

>>BY standard, if a class contains an empty object, that empty object is expected to occupy at least char's space, eg:

Isn't that what VC++ does?

Another interesting point: if you add std::printf("sizeof(d) = %d\n", sizeof(d)); to main(), VC++ 2010 reports 2 while Code::Blocks reports 1.
Visit Grandpa's Forums, a social networking forum, with family-oriented arcade games, blogs, discussion forums, and photo albums.

#7
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
Ancient Dragon:

Thank you for the effort.

Containing is different from inheritance:

class D: public B // inheritance
{
};


class D
{
B b; // Containment
};



It seems C++ standard only requires when a Empty class/struct object is contained, it should be differentiable from other object, hence it needs to occupy at least 1 character of space; in the case of inheritance, compiler may choose to Zero-size a empty base, this is what g++ and borland c++ (I believe) are doing; and a compiler may also choose to have empty base occupy some room, vc++, intel c++ belong to the latter. In other words, it's implementation defined.

Sometime, C++ standard leaves too much freedom for vendors so as to greatly reduced its usefulness.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users