Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

OK, so hopefully this is a subjective enough question for Programmers, but here goes. I am continuously broadening my knowledge of languages and software engineering practices... and I've run into something that just makes no sense to me whatsoever.

In C++, class declarations include private: methods and parameters in the header file, which, theoretically, is what you pass to the user to include if you make them a lib.

In Objective-C, @interfaces do pretty much the same thing, forcing you to list your private members (at least, there's a way to get private methods in the implementation file).

From what I can tell, Java and C# allow you to provide an interface/protocol which can declare all the publicly accessible properties/methods and gives the coder the ability to hide all implementation details in the implementation file.

Why? Encapsulation is one of the main principles of OOP, why do C++ and Obj-C lack this basic ability? Is there some kind of best-practices work-around for Obj-C or C++ that hides all implementation?

Thanks,

share|improve this question
4  
I feel your pain. I ran away screaming from C++ the first time I added a private field to a class and had to recompile everything that used it. –  Larry Coleman Dec 10 '10 at 17:12
    
@Larry, I don't mind it overly much, but it seems to be heralded as a great OO language, but it can't even encapsulate "properly." –  Stephen Furlani Dec 10 '10 at 18:46
2  
Don't believe the hype. There are better ways of doing OO, both in the static and dynamic typing camps. –  Larry Coleman Dec 10 '10 at 21:06
    
It's a great language in some ways, but not because of its OO abilities, which are a grafting of Simula 67 onto C. –  David Thornley Dec 10 '10 at 21:15
    
You should do some C programming. Then you will have a better understanding of why these languages are the way they are, including Java C# etc. –  Henry Dec 10 '10 at 23:02
add comment

3 Answers

up vote 4 down vote accepted

The question is whether the compiler needs to know how large an object is. If so, then the compiler has to know about the private members in order to count them up.

In Java, there's primitive types and objects, and all the objects are allocated separately, and the variables containing them are really pointers. Therefore, since a pointer is a fixed-size object, the compiler knows how big a thing a variable represents, without knowing the actual size of the pointed-to object. The constructor handles all of that.

In C++, it's possible to have objects represented locally or on the heap. Therefore, the compiler needs to know how big an object is, so that it can allocate a local variable or array.

Sometimes it's desirable to divide class functionality into a public interface and a private everything else, and that's where the PIMPL (Pointer to IMPLementation) technique comes in. The class will have a pointer to a private implementation class, and the public class methods can call that.

share|improve this answer
    
can't the compiler look to the object library to get this information? Why can't this information be machine-readable instead of human-readable? –  Stephen Furlani Dec 13 '10 at 14:10
    
@Stephen: At the time of compilation, there is not necessarily an object library. Since the size of objects affects the compiled code, it has to be known at compile time, not just at link time. Further, it's possible for A.h to define class A, B.h to define class B, and the function definitions in A.cpp to use objects of class B and vice versa. In that case, it would be necessary to compile each of A.cpp and B.cpp before the other, if taking object size from the object code. –  David Thornley Dec 13 '10 at 16:00
    
can't linking be done during compilation? I confess to not knowing details at that depth but if an object's interface exposes it's contents, can't those same contents be exposed from a library or other machine-readable component? must they be defined in a publicly accessible header file? I understand this is part of the majority of C languages, but does it have to be so? –  Stephen Furlani Dec 13 '10 at 16:04
    
@Stephen: Linking can only be done during compilation if all appropriate components are there. Even then, it would be a complicated process, involving partial compilation (everything but the object sizes), partial linking (to get the object sizes), then final compilation and linking. Given that C and C++ are relatively old languages, that just wasn't going to happen. Presumably somebody could design a new language without header files, but it wouldn't be C++. –  David Thornley Dec 13 '10 at 16:46
    
I see. Thanks for your insight, I appreciate it. –  Stephen Furlani Dec 13 '10 at 16:51
add comment

This all comes down to the design choice.

If you truly wish to hide the private implementation details of the C++ or Objective-C class, then you either provide one or more interfaces that the class supports (C++ pure virtual class, Objective-C @protocol) and/or you make the class able to construct itself by providing a static factory method or a class factory object.

The reason that the private variables are exposed in the header file/class declaration/@interface is that a consumer of your class might need to create a new instance of it and a new MyClass() or [[MyClass alloc]init] in the client code needs the compiler to understand how big a MyClass object is in order to do the allocation.

Java and C# also have their private variables detailed in the class - they are no exception to this, but IMO the interface paradigm is much more common with those languages. You may not have the source code in each case, but there's enough metadata in the compiled/byte-code to deduce this information. As C++ and Objective-C don't have this metadata, the only option is the actual details of the class/@interface. In the C++ COM world, you don't expose the private variables of any classes yet can provide the header file - because the class is pure virtual. A class factory object is registered to create the actual instances too, and there's some metadata in various forms.

In C++ and Objective-C, it is less work to hand out the header file compared to writing and maintaining an additional interface/@protocol file. This is one reason that you see the private implementation exposed so often.

Another reason in C++ is templates - the compiler needs to know the details of the class in order to generate a version of that class specialized to the parameters provided. The size of the class's members would vary with the parameterization, so it needs to have this information.

share|improve this answer
add comment

Due to the design of C++, in order to create an object on the stack the compiler must know how big it is. To do this it needs to have all the fields present in the header file, as that is all that the compiler can see when the header is included.

For instance if you define a class

class Foo {
    public int a;
    private int b;
};

then sizeof(Foo) is sizeof(a) + sizeof(b). If there was some mechanism to separate the private fields, then the header might contain

class Foo {
    public int a;
};

with sizeof(Foo) = sizeof(a) + ???.

If you want to really hide private data, try the pimpl idiom, with

class FooImpl;
class Foo {
    private FooImpl* impl;
}

in the header and a definition for FooImpl only in Foo's implementation file.

share|improve this answer
    
Oh. I had no idea this was the case. Is that why languages such as Java, C#, and Obj-C have "Class Objects" so they can ask the class how big the object should be? –  Stephen Furlani Dec 10 '10 at 13:28
4  
Try using a pimpl, a pointer to a private implementation. Since all class pointers are the same size you don't have to define the implementation class, only declare it. –  Scott Wales Dec 10 '10 at 13:30
    
I think that should be an answer instead of a comment. –  Larry Coleman Dec 10 '10 at 17:12
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.