tags:

views:

383

answers:

7

This might have been asked a million times before or might be incredibly stupid but why is it not implemented?

class A
{
      public:
             A(){ a = 5;}
             int a;
};

class B:public A
{
      public:
             B(){ a = 0.5;}
              float a;
};

int main()
{
    A * a = new B();

    cout<<a->a;
    getch();
    return 0;
}

This code will access A::a. How do I access B::a?

+2  A: 

You can downcast your variable to access B::a.

Something like:

((B*)a)->a

I think it is the same in most OO programming languages. I can't think of any one implementing virtual variables concept...

Pablo Santa Cruz
-1 for c-style casting.
Noah Roberts
@Noah you are just [too radical](http://stackoverflow.com/questions/3080764/this-pointer-in-macro-and-function) imho about this c style casting stuff (and as your own answer in that thread shows, you aren't as radical about your own answers. As of now it's still stating wrong things)
Johannes Schaub - litb
Isn't it about time you stopped crying about that? I gave your stupid two points back. No, I'm not too radical since I've seen the use of C-style casts screw just about everyone that's ever done so. If I delete my incorrect answer then it also deletes all comments, which is not necessarily a good thing, but I suppose since you insist and it is your response that instructs anyone who reads...I'll oblige.
Noah Roberts
Furthermore, it is entirely my right to knock down posts that contain problems and upgrade those that show what I see as the better approach. I simply comment on those I downgrade so they know why, which is a basic courtesy IMHO. So why don't you just go unwad those panties of yours and grow a pair?
Noah Roberts
@Noah sure, i like your passion. I find it sad you deleted your answer, i thought that you would like to edit your text and point to the comments section (which would have made me undo my downvote too -.-). Really, please just bear with me, i'm still kiddy inside, trolling on stackoverflow. lol
Johannes Schaub - litb
+3  A: 

(dynamic_cast<B*>(a))->a ? Why do you need that after all? Are virtual functions not enought?

Dark
@Dark: Just curious
Bruce
Mike Seymour
It is not possible to use `dynamic_cast` for downcasting non-polymorphic classes. The class in the OP's example is not polymorphic, which means that your `dynamic_cast` will not even compile.
AndreyT
Both commenters above are right.Anyways, using dynamic_cast usually a bad choice.All polymorphic behavior should be incapsulated into virtual functions.
Dark
+2  A: 

Leaving aside the argument that virtual methods should be private, virtual methods are intended as an extra layer of encapsulation (encapsulating variations in behavior). Directly accessing fields goes against encapsulation to begin with so it would be a bit hypocritical to make virtual fields. And since fields don't define behavior they merely store data, there isn't really any behavior to be virtualized. The very fact that you have a public int or float is an anti-pattern.

Cogwheel - Matthew Orlando
+8  A: 

By not making data public, and accessing them through virtual functions.

Consider for a moment, how what you ask for would have to be implemented. Basically, it would force any access to any data member to go through a virtual function. Remember, you are accessing data through a pointer to an A object, and class A doesn't know what you've done in class B.

In other words, we could make accessing any data member anywhere much slower -- or you could write a virtual method. Guess which C++'s designers chose..

James Curran
@James: Nice Answer!
Bruce
this is the whole problem solved by setters and getters.
Gary
+4  A: 

You can't do this and C++ does not support it because it breaks with fundamental C++ principles.

A float is a different type than an int, and name lookup as well as determining what conversions will be needed for a value assignment happens at compile time. However what is really named by a->a including its actual type would only be known at runtime.

You can use templates to parameterize class A

template<typename T>
class A
{
    public:
        // see also constructor initializer lists
        A(T t){ a = t; }
        T a;
};

Then you can pass the type, however only at compile time for the above mentioned principle's reason.

A<int> a(5); 
A<float> b(5.5f);
Johannes Schaub - litb
+14  A: 

To access B::a:

cout << static_cast<B*>(a)->a;

To explicitly access both A::a and B::a:

cout << static_cast<B*>(a)->A::a;
cout << static_cast<B*>(a)->B::a;

(dynamic_cast is sometimes better than static_cast, but it can't be used here because A and B are not polymorphic.)

As to why C++ doesn't have virtual variables: Virtual functions permit polymorphism; in other words, they let a classes of two different types be treated the same by calling code, with any differences in the internal behavior of those two classes being encapsulated within the virtual functions.

Virtual member variables wouldn't really make sense; there's no behavior to encapsulate with simply accessing a variable.

Also keep in mind that C++ is statically typed. Virtual functions let you change behavior at runtime; your example code is trying to change not only behavior but data types at runtime (A::a is int, B::a is float), and C++ doesn't work that way. If you need to accommodate different data types at runtime, you need to encapsulate those differences within virtual functions that hide the differences in data types. For example (demo code only; for real code, you'd overload operator<< instead):

class A
{
  public:
         A(){ a = 5;}
         int a;
         virtual void output_to(ostream& o) const { o << a; }
};

class B:public A
{
  public:
         B(){ a = 0.5;}
         float a;
         void output_to(ostream& o) const { o << a; }
};

Also keep in mind that making member variables public like this can break encapsulation and is generally frowned upon.

Josh Kelley
+1  A: 

This isn't supported by C++ because it violates the principles of encapsulation.

Your classes should expose and implement a public (possibly virtual) interface that tells class users nothing about the internal workings of your class. The interface should describe operations (and results) that the class can do at an abstract level, not as "set this variable to X".

Mark B