Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to subclass a C struct in C++ and use pointers to the struct in C code?

Tags:

c++

c

gcc

extern-c

Is there a side effect in doing this:

C code:

struct foo {
      int k;
};

int ret_foo(const struct foo* f){ 
    return f.k; 
}

C++ code:

class bar : public foo {

   int my_bar() { 
       return ret_foo( (foo)this ); 
   }

};

There's an extern "C" around the C++ code and each code is inside its own compilation unit.

Is this portable across compilers?

like image 444
Edu Felipe Avatar asked Sep 24 '08 13:09

Edu Felipe


People also ask

Can a struct have pointers in it?

Declaring a structure pointer is similar to the declaration of a structure variable. To declare a structure pointer struct keyword is used followed by the structure name and pointer name with an asterisk * symbol. Members of a structure can be accessed from pointers using two ways that are.

Can you subclass a struct C++?

This is entirely legal. In C++, classes and structs are identical concepts, with the exception that all struct members are public by default. That's the only difference.

Can a struct inherit from another class?

A struct cannot inherit from another kind of struct, whereas classes can build on other classes. You can change the type of an object at runtime using typecasting. Structs cannot have inheritance, so have only one type. If you point two variables at the same struct, they have their own independent copy of the data.

Can we inherit struct in C?

No you cannot. C does not support the concept of inheritance.


4 Answers

I certainly not recommend using such weird subclassing. It would be better to change your design to use composition instead of inheritance. Just make one member

foo* m_pfoo;

in the bar class and it will do the same job.

Other thing you can do is to make one more class FooWrapper, containing the structure in itself with the corresponding getter method. Then you can subclass the wrapper. This way the problem with the virtual destructor is gone.

like image 28
m_pGladiator Avatar answered Oct 04 '22 03:10

m_pGladiator


This is entirely legal. In C++, classes and structs are identical concepts, with the exception that all struct members are public by default. That's the only difference. So asking whether you can extend a struct is no different than asking if you can extend a class.

There is one caveat here. There is no guarantee of layout consistency from compiler to compiler. So if you compile your C code with a different compiler than your C++ code, you may run into problems related to member layout (padding especially). This can even occur when using C and C++ compilers from the same vendor.

I have had this happen with gcc and g++. I worked on a project which used several large structs. Unfortunately, g++ packed the structs significantly looser than gcc, which caused significant problems sharing objects between C and C++ code. We eventually had to manually set packing and insert padding to make the C and C++ code treat the structs the same. Note however, that this problem can occur regardless of subclassing. In fact we weren't subclassing the C struct in this case.

like image 107
Derek Park Avatar answered Oct 04 '22 02:10

Derek Park


“Never derive from concrete classes.” — Sutter

“Make non-leaf classes abstract.” — Meyers

It’s simply wrong to subclass non-interface classes. You should refactor your libraries.

Technically, you can do what you want, so long as you don’t invoke undefined behavior by, e. g., deleting a pointer to the derived class by a pointer to its base class subobject. You don’t even need extern "C" for the C++ code. Yes, it’s portable. But it’s poor design.

like image 24
Roman Odaisky Avatar answered Oct 04 '22 04:10

Roman Odaisky


This is perfectly legal, though it might be confusing for other programmers.

You can use inheritance to extend C-structs with methods and constructors.

Sample :

struct POINT { int x, y; }
class CPoint : POINT
{
public:
    CPoint( int x_, int y_ ) { x = x_; y = y_; }

    const CPoint& operator+=( const POINT& op2 )
    { x += op2.x; y += op2.y; return *this; }

    // etc.
};

Extending structs might be "more" evil, but is not something you are forbidden to do.

like image 45
Christopher Avatar answered Oct 04 '22 04:10

Christopher