So I'm working on a personal project (trying to get better at c++), and I'm trying to get this working:
I have an ABC class A
with a pure virtual function interactWith(A* target);
I then have two derived classes, class B and class C.
However, class B must interactWith class C differently than with another class B
I found one way of doing this with an if/else and a virtual getType() in the ABC, but I was curious if there was a more elegant way or if I'm just doing something very stupid, and if I am doing something stupid (which is very possible), where would I begin searching for a better solution (i.e. a more appropriate design pattern)
Please note: I'm not using boost, and I'd rather avoid it for now, and start learning it when I'm actually good at programming
Any help you could provide would be welcome. Please and thankyou
Something I should note: classes B and C will (should) only be visible via an A*
What you are trying to implement is called double dispatch: a function that behaves as virtual with respect to two objects.
There are several ways to implement it, one of the more common being the use of visitor pattern.
Scott Meyers has an excellent chapter on implementing double dispatch (Item #31 in his "More Effective C++" book). He starts with the discussion of the visitor pattern, and then proceeds to a very nice implementation with RTTI.
You almost never want to use type-switching. Dynamic casting is a little better, but still to be avoided if possible.
A better alternative is to turn things around so you can use the virtual dispatch mechanism again, often called "double dispatch" or "simulating multi-methods". It will look something like this:
struct B;
struct A {
virtual void interactWith(A* target);
virtual void interactWithB(B* target);
};
struct B : A {
virtual void interactWith(A* target) {
target->interactWithB(this);
}
virtual void interactWithB(B* lhs) {
// B vs. B stuff goes here, but with lhs and this in place of this and target
}
};
struct C : A {
virtual void interactWith(A* target) {
// C vs. anything stuff goes here
}
virtual void interactWithB(B* lhs) {
// B vs. C stuff goes here, again backward
}
};
Use dynamic_cast
C* cTarget = dynamic_cast<C*>(target);
if(cTarget == NULL)
{
//cTarget is not a C
}
else if(cTarget)
{
//cTarget is a C
}
dynamic_cast does some fancy stuff(I'm not sure what it does) to make sure that the cast is valid, and if it is not, it returns NULL.
Ideally, encapsulate the behavior that needs to be different between a B and a C when interacting with it, and put it into another virtual method that you call on target -- there will then be different implementations of that method in B and C as appropriate.
If the above gets too confused and too scattered, that's an indication that you've chosen the wrong abstractions to be your objects. You might be better off scrapping the A/B/C class hierarchy and dividing up your program into a different hierarchy, but without a more concrete description of what you are trying to do its impossible to say. Premature abstraction (along with premature optimization) is one of the key mistakes inexperienced programmers often make.
Related
I have got the following data structure:
class Element {
std::string getType();
std::string getId();
virtual std::vector<Element*> getChildren();
}
class A : public Element {
void addA(const A *a);
void addB(const B *b);
void addC(const C *c);
std::vector<Element*> getChildren();
}
class B : public Element {
void addB(const B *b);
void addC(const C *c);
std::vector<Element*> getChildren();
}
class C : public Element {
int someActualValue;
}
/* The classes also have some kind of container to store the pointers and
* child elements. But let's keep the code short. */
The data structure is used to pruduce a acyclic directed graph. The C class acts as a "leaf" containing actual data for algebra-tasks. A and B hold other information, like names, types, rules, my favourite color and the weather forecast.
I want to program a feature, where a window pops up and you can navigate through an already existing structure. On the way i want to show the path the user took with some pretty flow chart, which is clickable to go back in the hierarchy. Based on the currently visited Graph-Node (which could be either A, B or C) some information has to be computed and displayed.
I thought i could just make a std::vector of type Element* and use the last item as the active element i work with. I thought that was a pretty nice approach, as it makes use of the inheritance that is already there and keeps the code i need quite small.
But i have a lot of situations like these:
Element* currentElement;
void addToCurrentElement(const C *c) {
if(A *a = dynamic_cast<A*>(currentElement)) {
//doSomething, if not, check if currentElement is actually a B
}
}
Or even worse:
vector<C*> filterForC's(A* parent) {
vector<Element*> eleVec = parent.getChildren();
vector<C*> retVec;
for(Element* e : eleVec) {
if (e.getType() == "class C") {
C *c = dynamic_cast<C*>(e);
retVec.append(c);
}
}
}
It definitely is object oriented. It definitely does use inheritance. But it feels like i just threw all the comfort OOP gives me over board and decided to use raw pointers and bitshifts again. Googling the subject, i found a lot of people saying casting up/down is bad design or bad practice. I totally believe that this is true, but I want to know why exactly. I can not change most of the code as it is part of a bigger project, but i want to know how to counter something like this situation when i design a program in the future.
My Questions:
Why is casting up/down considered bad design, besides the fact that it looks horrible?
Is a dynamic_cast slow?
Are there any rules of thumb how i can avoid a design like the one i explained above?
There are a lot of questions on dynamic_cast here on SO. I read only a few and also don't use that method often in my own code, so my answer reflects my opinion on this subject rather than my experience. Watch out.
(1.) Why is casting up/down considered bad design, besides the fact that it looks horrible?
(3.) Are there any rules of thumb how i can avoid a design like the one i explained above?
When reading the Stroustrup C++ FAQ, imo there is one central message: don't trust the people which say never use a certain tool. Rather, use the right tool for the task at hand.
Sometimes, however, two different tools can have a very similar purpose, and so is it here. You basically can recode any functionality using dynamic_cast through virtual functions.
So when is dynamic_cast the right tool? (see also What is the proper use case for dynamic_cast?)
One possible situation is when you have a base class which you can't extend, but nevertheless need to write overloaded-like code. With dynamic-casting you can do that non-invasive.
Another one is where you want to keep an interface, i.e. a pure virtual base class, and don't want to implement the corresponding virtual function in any derived class.
Often, however, you rather want to rely on virtual function -- if only for the reduced uglyness. Further it's more safe: a dynamic-cast can fail and terminate your program, a virtual function call (usually) won't.
Moreover, implemented in terms of pure functions, you will not forget to update it in all required places when you add a new derived class. On the other hand, a dynamic-cast can easily be forgotten in the code.
Virtual function version of your example
Here is the example again:
Element* currentElement;
void addToCurrentElement(const C *c) {
if(A *a = dynamic_cast<A*>(currentElement)) {
//doSomething, if not, check if currentElement is actually a B
}
}
To rewrite it, in your base add a (possibly pure) virtual functions add(A*), add(B*) and add(C*) which you overload in the derived classes.
struct A : public Element
{
virtual add(A* c) { /* do something for A */ }
virtual add(B* c) { /* do something for B */ }
virtual add(C* c) { /* do something for C */ }
};
//same for B, C, ...
and then call it in your function or possibly write a more concise function template
template<typename T>
void addToCurrentElement(T const* t)
{
currentElement->add(t);
}
I'd say this is the standard approach. As mentioned, the drawback could be that for pure virtual functions you require N*N overloads where maybe N might be enough (say, if only A::add requires a special treatment).
Other alternatives might use RTTI, the CRTP pattern, type erasure, and possibly more.
(2.) Is a dynamic_cast slow?
When considering what the majority of answers throughout the net state, then yes, a dynamic cast seems to be slow, see here for example.
Yet, I don't have practical experience to support or disconfirm this statement.
I am a decent procedural programmer, but I am a newbie to object orientation (I was trained as an engineer on good old Pascal and C). What I find particularly tricky is choosing one of a number of ways to achieve the same thing. This is especially true for C++, because its power allows you to do almost anything you like, even horrible things (I guess the power/responsibility adage is appropriate here).
I thought it might help me to run one particular case that I'm struggling with by the community, to get a feel for how people go about making these choices. What I'm looking for is both advice pertinent to my specific case, and also more general pointers (no pun intended). Here goes:
As an exercise, I am developing a simple simulator where a "geometric representation" can be of two types: a "circle", or a "polygon". Other parts of the simulator will then need to accept these representations, and potentially deal with them differently. I have come up with at least four different ways in which to do this. What are the merits/drawbacks/trade-offs of each?
A: Function Overloading
Declare Circle and Polygon as unrelated classes, and then overload each external method that requires a geometric representation.
B: Casting
Declare an enum GeometricRepresentationType {Circle, Polygon}. Declare an abstract GeometricRepresentation class and inherit Circle and Polygon from it. GeometricRepresentation has a virtual GetType() method that is implemented by Circle and Polygon. Methods then use GetType() and a switch statement to cast a GeometricRepresentation to the appropriate type.
C: Not Sure of an Appropriate Name
Declare an enum type and an abstract class as in B. In this class, also create functions Circle* ToCircle() {return NULL;} and Polygon* ToPolygon() {return NULL;}. Each derived class then overloads the respective function, returning this. Is this simply a re-invention of dynamic casting?
D: Bunch Them Together
Implement them as a single class having an enum member indicating which type the object is. The class has members that can store both representations. It is then up to external methods not to call silly functions (e.g. GetRadius() on a polygon or GetOrder() on a circle).
Here are a couple of design rules (of thumb) that I teach my OO students:
1) any time you would be tempted to create an enum to keep track of some mode in an object/class, you could (probably better) create a derived class for each enum value.
2) any time you write an if-statement about an object (or its current state/mode/whatever), you could (probably better) make a virtual function call to perform some (more abstract) operation, where the original then- or else-sub-statement is the body of the derived object's virtual function.
For example, instead of doing this:
if (obj->type() == CIRCLE) {
// do something circle-ish
double circum = M_PI * 2 * obj->getRadius();
cout << circum;
}
else if (obj->type() == POLY) {
// do something polygon-ish
double perim = 0;
for (int i=0; i<obj->segments(); i++)
perm += obj->getSegLength(i);
cout << perim;
}
Do this:
cout << obj->getPerimeter();
...
double Circle::getPerimeter() {
return M_PI * 2 * obj->getRadius();
}
double Poly::getPerimeter() {
double perim = 0;
for (int i=0; i<segments(); i++)
perm += getSegLength(i);
return perim;
}
In the case above it is pretty obvious what the "more abstract" idea is, perimeter. This will not always be the case. Sometimes it won't even have a good name, which is one of the reasons it's hard to "see". But, you can convert any if-statement into a virtual function call where the "if" part is replaced by the virtual-ness of the function.
In your case I definitely agree with the answer from Avi, you need a base/interface class and derived subclasses for Circle and Polygon.
Most probably you'll have common methods between the Polygon and Circle. I'd combine them both under an interface named Shape, for example(writing in java because it's fresher in my mind syntax-wise. But that's what I would use if I wrote c++ example. It's just been a while since I wrote c++):
public interface Shape {
public double getArea();
public double getCentroid();
public double getPerimiter();
}
And have both Polygon and Circle implement this interface:
public class Circle implements Shape {
// Implement the methods
}
public class Polygon implements Shape {
// Implement the methods
}
What are you getting:
You can always treat Shape as a generelized object with certain properties. You'll be able to add different Shape implementations in the future without changing the code that does something with Shape (unless you'll have something specific for a new Shape)
If you have methods that are exactly the same, you can replace the interface with abstract class and implement those (in C++ interface is just an abstract class with nothing implemented)
Most importantly (I'm emphesizing bullet #1) - you'll enjoy the power of polymorphism. If you use enums to declare your types, you'll one day have to change a lot of places in the code if you want to add new shape. Whereas, you won't have to change nothing for a new class the implements shape.
Go through a C++ tutorial for the basics, and read something like Stroustrup's "The C++ programming language" to learn how to use the language idiomatically.
Do not believe people telling you you'd have to learn OOP independent of the language. The dirty secret is that what each language understands as OOP is by no means even vaguely similar in some cases, so having a solid base in, e.g. Java, is not really a big help for C++; it goes so far that the language go just doesn't have classes at all. Besides, C++ is explicitly a multi-paradigm language, including procedural, object oriented, and generic programming in one package. You need to learn how to combine that effectively. It has been designed for maximal performance, which means some of the lower-bit stuff shows through, leaving many performance-related decisions in the hands of the programmer, where other languages just don't give options. C++ has a very extensive library of generic algorithms, learning to use those is required part of the curriculum.
Start small, so in a couple year's time you can chuckle fondly over the naïveté of your first attempts, instead of pulling your hair out.
Don't fret over "efficiency," use virtual member functions everywhere unless there is a compelling reason not to. Get a good grip on references and const. Getting an object design right is very hard, don't expect the first (or fifth) attempt to be the last.
First, a little background on OOP and how C++ and other languages like Java differ.
People tend to use object-oriented programming for several different purposes:
Generic programming: writing code that is generic; i.e. that works on any object or data that provides a specified interface, without needing to care about the implementation details.
Modularity and encapsulation: preventing different pieces of code from becoming too tightly coupled to each other (called "modularity"), by hiding irrelevant implementation details from its users.
It's another way to think about separation of concerns.
Static polymorphism: customizing a "default" implementation of some behavior for a specific class of objects while keeping the code modular, where the set of possible customizations is already known when you are writing your program.
(Note: if you didn't need to keep the code modular, then choosing behavior would be as simple as an if or switch, but then the original code would need to account for all of the possibilities.)
Dynamic polymorphism: like static polymorphism, except the set of possible customizations is not already known -- perhaps because you expect the user of the library to implement the particular behavior later, e.g. to make a plug-in for your program.
In Java, the same tools (inheritance and overriding) are used for solving basically all of these problems.
The upside is that there's only one way to solve all of the problems, so it's easier to learn.
The downside is a sometimes-but-not-always-negligible efficiency penalty: a solution that resolves concern #4 is more costly than one that only needs to resolve #3.
Now, enter C++.
C++ has different tools for dealing with all of these, and even when they use the same tool (such as inheritance) for the same problem, they are used in such different ways that they are effectively completely different solutions than the classic "inherit + override" you see in Java:
Generic programming: C++ templates are made for this. They're similar to Java's generics, but in fact Java's generics often require inheritance to be useful, whereas C++ templates have nothing to do with inheritance in general.
Modularity and encapsulation: C++ classes have public and private access modifiers, just like in Java. In this respect, the two languages are very similar.
Static polymorphism: Java has no way of solving this particular problem, and instead forces you to use a solution for #4, paying a penalty that you don't necessarily need to pay. C++, on the other hand, uses a combination of template classes and inheritance called CRTP to solve this problem. This type of inheritance is very different from the one for #4.
Dynamic polymorphism: C++ and Java both allow for inheritance and function overriding, and are similar in this respect.
Now, back to your question. How would I solve this problem?
It follows from the above discussion that inheritance isn't the single hammer meant for all nails.
Probably the best way (although perhaps the most complicated way) is to use #3 for this task.
If need be, you can implement #4 on top of it for the classes that need it, without affecting other classes.
You declare a class called Shape and define the base functionality:
class Graphics; // Assume already declared
template<class Derived = void>
class Shape; // Declare the shape class
template<>
class Shape<> // Specialize Shape<void> as base functionality
{
Color _color;
public:
// Data and functionality for all shapes goes here
// if it does NOT depend on the particular shape
Color color() const { return this->_color; }
void color(Color value) { this->_color = value; }
};
Then you define the generic functionality:
template<class Derived>
class Shape : public Shape<> // Inherit base functionality
{
public:
// You're not required to actually declare these,
// but do it for the sake of documentation.
// The subclasses are expected to define these.
size_t vertices() const;
Point vertex(size_t vertex_index) const;
void draw_center(Graphics &g) const { g.draw_pixel(shape.center()); }
void draw_outline()
{
Derived &me = static_cast<Derived &>(*this); // My subclass type
Point p1 = me.vertex(0);
for (size_t i = 1; i < me.vertices(); ++i)
{
Point p2 = me.vertex(1);
g.draw_line(p1, p2);
p1 = p2;
}
}
Point center() const // Uses the methods above from the subclass
{
Derived &me = static_cast<Derived &>(*this); // My subclass type
Point center = Point();
for (size_t i = 0; i < me.vertices(); ++i)
{ center += (center * i + me.vertex(i)) / (i + 1); }
return center;
}
};
Once you do that, you can define new shapes:
template<>
class Square : public Shape<Square>
{
Point _top_left, _bottom_right;
public:
size_t vertices() const { return 4; }
Point vertex(size_t vertex_index) const
{
switch (vertex_index)
{
case 0: return this->_top_left;
case 1: return Point(this->_bottom_right.x, this->_top_left.y);
case 2: return this->_bottom_right;
case 3: return Point(this->_top_left.x, this->_bottom_right.y);
default: throw std::out_of_range("invalid vertex");
}
}
// No need to define center() -- it is already available!
};
This is probably the best method since you most likely already know all possible shapes at compile-time (i.e. you don't expect the user will write a plug-in to define his own shape), and thus don't need any of the whole deal with virtual. Yet it keeps the code modular and separates the concerns of the different shapes, effectively giving you the same benefits as a dynamic-polymorphism approach.
(It is also the most efficient option at run-time, at the cost of being a bit more complicated at compile-time.)
Hope this helps.
EDIT: To be clear—right off the bat—this is a question about the linguistic abilities of a modern C++ compiler. Not a question about a specific goal. It's hard to describe such an abstract concept without clarifying this first and I've realized that some of the confusion revolves around what is commonly done rather than what can possibly be done. This is a very abstract question. Nothing here will compile and this is on purpose. Likewise, I'm not asking how to make this specific case work, but I'm asking if there's a way to get C++ to recognize what I would like to do (via templating or some kind of auto->decltype trick most likely if even possible).
I'm not exactly new to C++, but certainly not an expert. This is a fundamental problem that I've been struggling with since I've rediscovered the power of the language. The end goal here is to elegantly (and with as little code as possible) forward proper polymorphic return values based on calling context. For example...
class A {
public:
A& foo() {
// do something mutant fooish
return *this;
};
};
class B: public A {
public:
B& bar() {
// do something mutant barish
return *this;
};
};
int main(int argc, char** argv) {
B yarp;
yarp.foo().bar();
};
Compile error. Makes sense, C++ is designed to assume that you know nothing about what you're doing (which makes it highly optimizable but sometimes a pain... a high-level-mid-level OOP language).
Obvioiusly C++ compilers have gotten to the point where they're not only aware of what you are asking for (the A().foo() works and B().foo() works scenario), but also in what context your asking for it in (hence auto yarp = B() in C++11, the compiler knows that yarp is an instance of B). Is there a way to leverage this elegantly without having to reproduce a bunch of "using" statements or wrapped methods (which strangely don't get optimized out according to disassemble of gcc binaries)?
So is there a trick here? Something I simply haven't learned online. An auto -> decltype trick or a templating trick? Example:
class A {
public:
template <typename R>
R& foo() {
// do something fooish
return (R&)*this;
};
};
class B: public A {
public:
using A::foo<A>; // << even this would be better than nothing (but no where near optimum)
B& bar() {
// do something barish
return *this;
};
};
Something even simpler? If you expand this concept to operators of a proxy template class meant for reference counting and gc deallocation, it becomes clear how problematic this becomes. Thanks in advance for any help (oh, and first post on stackoverflow, so if I got any formatting wrong or you have suggestions for a better structured post, apologies around and please point them out).
The obvious solution would be to just seperate it out into two lines:
yarp.foo();
yarp.bar();
or, alternatively, use static_cast's to get back a reference to B&, so
static_cast<B&>(yarp.foo()).bar();
Agreed, that's a little bit more verbose but chaining multiple member-function calls in a heirarchy in one line together like this is pretty unusual syntax for C++. It just doesn't come up a whole lot, so the language doesn't support that idiom terribly well. I have never come across a situation where I ran into this issue yet.
If you want to design some chainable functionality, there are other, better idioms you can use. One example is Boost's Range Adaptors that overload operator| to achieve chaining.
EDIT: Another option is to overload foo() in B&:
class B: public A {
public:
B& foo() { A::foo(); return *this; }
B& bar() {
// do something mutant barish
return *this;
};
};
I don't think there is a auto type detection since compiler even doesn't know what classes will inherit A.
And in your second trial, C++ forbid using a template specialization. So that won't compile.
I think there is another trick you could try is to make A a template
template <typename FinalType>
class A {
public:
FinalType& foo() {
// do something fooish
return static_cast<FinalType&>(*this);
};
};
class B: public A<B> {
public:
B& bar() {
// do something barish
return *this;
};
};
Erm you declare a instance of class B which has no method foo - so no wonder there is a compile error - did you mean
yarp.bar().foo();
I have two classes that are almost identical, besides one method. The classes have the same data part and all the member functions but one:
class A {
private:
double data;
public:
double calc(){
return data*data;
}
double especific(){
return 2.0*data;
}
}
and the second class is identical, besides the especific method.
This member function in particular needs all the member data to calculate, so passing by value or reference is not an option. Is there a way to implement this without a lot of code duplication? Either using only one class or using templates, but not inheritance (huge performance impact).
Thanks
EDIT: Thanks for all the responses. The Strategy pattern can help in my case, I will try it and see if it works. I'm avoiding virtual inheritance as the plague based on some tests that I did in a different program. This routine will be called everywhere, and performance is a very important factor.
This sounds like a job for the Strategy pattern. It can be implemented in this case as a template parameter. Often it would be implemented as a constructor parameter or a setter method on the class, but that would require inheritance to work properly.
In this case, something like:
template <class SpecificStrategy>
class A {
private:
double data;
public:
double calc(){
return data*data;
}
double especific() {
return SpecificStrategy::especific(data);
}
};
class DoubleStrategy {
static double especific(double data) {
return 2 * data;
}
};
class TripleStrategy {
static double especific(double data) {
return 3 * data;
}
};
Then you can refer to:
A<DoubleStrategy> x;
A<TripleStrategy> y;
x and y will be of completely unrelated types, but it sounds like that's not what you want in this case.
Now, in my opinion using a virtual function and inheritance is the way to go. As someone else pointed out, the performance penalty isn't that large. However there are circumstances in which I could see that it would be a bad idea.
For example, if this class is intended to represent a vector in a graphics package and you're going to be doing the same transform to millions of them, then I could see how you would not want a virtual function call to be a part of the code that did the transform. In fact, you would want to avoid pointer dereferences of any kind of you could at all help it.
Maybe I'm missing the point but why not have a base class that implements all the common functionality and a pure virtual especific() and then inherit this and have the child classes implement especific() as required. Make the data member protected.
class BaseA
{
protected:
double data;
public:
double calc(){
return data*data;
}
virtual double especific() = 0;
};
class A1 : BaseA
{
double especific()
{
return data * 2;
}
};
WRT to the huge performance impact of inheritance... I think this isn't likely unless the cost of vtable lookups is significant compared with the work being done in the method body and you're doing this in a tight loop what's consuming most of your application processing.
If you don't make any members virtual and define your classes intelligently there should be no performance impact whatsoever from inheritence.
All inheritence is saying is "make this class like that one, but with this extra stuff". It is no different at runtime than if you'd typed the same stuff twice.
I suppose you could make a performance impact by doing a bunch of unnesscary stuff in the constructor for the parent class that the child classes don't need. But you won't be that stupid. I have faith in you.
Why two classes at all? If the classes share the same data, you may just want to implement both functions in one class.
class A {
private:
double data;
public:
double calc(){
return data*data;
}
double especific(){
return 2.0*data;
}
double eMoreSpecific() {
return 23.0*data;
}
have a base class with all the common stuff and derive the two classes from it
As others have pointed out
a) this is exactly what inheritance was designed for
b) there is no perfomance overhead whatsoever
c) there are no nasty gotchas lurking anywhere
Many people will comment on this and say 'ah but what about xxxx'; these will be valid comments for advanced and corner case use; except you are not going to do any of them based on the simplicity of what you asked for.
Check out the Strategy Pattern
You could have your class take a functor which especific then calls. You can supply different functors for different ways of calculating the output. There are several other ways you can implement Strategy as well.
I have a feeling that a Bridge pattern might be a good approach for you as it sounds like you want to have unique implementations for your common abstraction.
There are several ways to do this, many of which you've named:
Inheritance from a common base class (which does most of the work), and virtual especific()
One class, with two slightly differently-named especific() methods (or overloaded methods)
Use template specialisation
Have A and B use some other class C to do the majority of the work.
There may be others.
You'll need to choose one of these based on the semantics of your classes and application, and any other specific constraints or requirements.
check out the "inheritance pattern"
I read that early C++ "compilers" actually translated the C++ code to C and used a C compiler on the backend, and that made me wonder. I've got enough technical knowledge to wrap my head around most of how that would work, but I can't figure out how to do class inheritance without having language support for it.
Specifically, how do you define a class with a few fields, then a bunch of subclasses that inherit from it and each add their own new fields, and be able to pass them around interchangeably as function arguments? And especially how can you do it when C++ allows you to allocate objects on the stack, so you might not even have pointers to hide behind?
NOTE: The first couple answers I got were about polymorphism. I know all about polymorphism and virtual methods. I've even given a conference presentation once about the low-level details of how the virtual method table in Delphi works. What I'm wondering about is class inheritance and fields, not polymorphism.
In C anyway you an do it the way cfront used to do it in the early days of C++ when the C++ code was translated into C. But you need to be quite disciplined and do all the grunt work manually.
Your 'classes' have to be initialized using a function that performs the constructor's work. this will include initializing a pointer to a table of polymorphic function pointers for the virtual functions. Virtual function calls have to be made through the vtbl function pointer (which will point to a structure of function pointers - one for each virtual function).
The virtual function structure for each derived calss needs to be a super-set of the one for the base class.
Some of the mechanics of this might be hidden/aided using macros.
Miro Samek's first edition of "Practical Statecharts in C/C++" has an Appendix A - "C+ - Object Oriented Programming in C" that has such macros. It looks like this was dropped from the second edition. Probably because it's more trouble than it's worth. Just use C++ if you want to do this...
You should also read Lippman's "Inside the C++ Object Model" which goes into gory details about how C++ works behind the scenes, often with snippets of how things might work in C.
I think I see what you're after. Maybe.
How can something like this work:
typedef
struct foo {
int a;
} foo;
void doSomething( foo f); // note: f is passed by value
typedef
struct bar {
foo base;
int b;
} bar;
int main() {
bar b = { { 1 }, 2};
doSomething( b); // how can the compiler know to 'slice' b
// down to a foo?
return 0;
}
Well you can't do that as simply as that without language support - you'd need to do some things manually (that's what it means to not have language support):
doSomething( b.base); // this works
Basically, structs-within-structs.
struct Base {
int blah;
};
struct Derived {
struct Base __base;
int foo;
};
When you want to, say, cast a Derived * to Base *, you'd actually return a pointer to the __base element of the Derived struct, which in this case is the first thing in the struct so the pointers should be the same (wouldn't be the case for multiple-inherited classes though).
If you want to access blah in this case, you would do something like derived.__base.blah.
Virtual functions are normally done with a special table of function pointers that is part of each object, a rudimentary sort of "what is my type" record.
Here is how COM does it for C language. I am a bit rusty at this , but the essence works like this. Each "class" member variables is just a struct.
struct Shape
{
int value;
};
struct Square
{
struct Shape shape; // make sure this is on top, if not KABOOM
int someothervalue;
};
all the methods, are actually just normal functions. like this
void Draw(Shape * shape,int x,int y)
{
shape->value=10; // this should work even if you put in a square. i think...
}
then, they use the preprocessor to "trick" the C code into displaying something like this.
Square * square;
square->Draw(0,0); // this doesnt make sense, the preprocessor changes it to Draw(square,0,0);
Alas, i dont know what kind of preprocessor tricks are done to make the C++ looking function call resolve into a plan vanilla C call.
DirectX COM objects are declared this way.
Dr. Dobb's had a moderately detailed article on this topic, Single Inheritance Classes in C.
Structs-within-structs is common, but it makes it a pain to access inherited fields. You either need to use indirection (e.g. child->parent.field), or casting (((PARENT *) child)->field).
An alternative I have seen is more like this:
#define COUNTRY_FIELDS \
char *name; \
int population;
typedef struct COUNTRY
{
COUNTRY_FIELDS
} COUNTRY;
#define PRINCIPALITY_FIELDS \
COUNTRY_FIELDS \
char *prince;
typedef struct PRINCIPALITY
{
PRINCIPALITY_FIELDS
} PRINCIPALITY;
This gives types with direct access to inherited fields. The resulting objects can still be safely cast to the parent type, because the parent's fields and the inherited fields start at the same place.
The syntax can be improved a little with macros. I saw this in the older POV-Ray source (but I think they've since converted to C++).
If you want a good reference on how this stuff works take a look at the glib/gdk/gtk open source libraries. They have pretty good documentation and the entire framework is based on C OO.
You can simulate an object by writing constructors, setters, getters, and destructors with the hidden this pointer called out explicitly.
Inheritance is handled by having the derived object include a pointer to the base object in the structure of the derived object.