I'm working on the graphics code for a game library in Java. I made package called com.engine.graphics. In this package, I have a lower-level class called VertexArrayObject. This class is used by "client-level" classes that clients will use; however, I do not want to give clients access to VertexArrayObject, since it would only serve to complicate their understanding of my library. Thus, I gave VertexArrayObject the default access specifier; that way, only classes within com.engine.graphicshave access to it, and also tells clients that they do not need to know what it is.
Just like there is this standard convention for Java, I figured there must be some standard convention for C++ for dealing with this; however, my internet searches have yielded no results.
So, my question is, what is the convention? And if there isn't one, what is the best approach?
C++ does not have a notion of 'package' thus no 'package-protection' is technically possible. (There is a proposition for modules, but it will not be included even in the upcoming C++17 standard).
There are many ways of hiding the class from external world or restricting access to it, on syntax level you can resort to:
nested classes which may be declared private (you should be familiar with them from Java, except they are "static" by default and cannot access non-static enclosing class members) link;
friend classes that can access any private members of the given class link;
friend functions if you want to restrict access to only certain functions, including member functions of another class;
private/protected inheritance where only the class members are aware of the inheritance link.
Having a lot of friend classes and functions is a mess, but there is a reason for requiring explicit listing of those: they break the encapsulation principle.
Finally, you can use either "private implementation" idiom (aka pimpl, aka opaque pointer) that consists in defining a visible class holding a pointer to the implementation class and forwarding all calls while the implementation class is defined in a separate cpp file or the façade design pattern.
Chose whatever seems appropriate for the given class relation. Standard library tends to prefer nested classes while Qt, a popular graphic library, relies on pimpl.
Related
Whats the significance of classes over data-structures or data-structures over classes?
Ok so The most basic ones can be that we can use "Access Specifiers In Classes" meaning we can prevent some and allow some to access our data.
next can be that data-hiding.
But whats the main thing that separates classes and data-structures? I mean why need data-structures when we have classes or vice-versa?
C++ has fundamantal types, and classes.
Struct and Class are both keywords that introduce a new class. There are slightly different defaults.
Data structures are an arrangement of data with some kind of invarient. They can be a class, they can contain classes, or they could be completely class free.
They are different categories of thing. It is like asking what the difference is between steel and an automobile.
In a course assignment, what the teacher is asking for is for you to know the definition the teacher or the text taught those terms meant. Terms mean what the context they are in tells them to mean. It is a matter of "are you paying attention" not "do you know this fact"; having asked it of the internet, you have already failed.
In terms of syntax, in C++ the only difference between a class and a struct is that members of a struct are public by default, while the members of a class are private by default.
From a perspective of implied design intent, however, there is a larger difference. struct was/is a feature of C, and was/is used (in both C and C++) to help the programmer organize Plain Old Data in useful ways. (for example, if you know every Person in your persons-database needs to store the person's first name, last name, and age, then you can put two char arrays and and int together in a struct Person and thereby make it more convenient to track all of that data as a unit, than if you had to store each of those fields separately).
C++ continues to provide that C-style struct functionality, but then goes further by adding additional features to better support object-oriented-programming. In particular, C++ adds explicit support for encapsulation (via the private and protected keywords), functionality-extension via inheritance, the explicit tying-together of code and data via methods, and run-time polymorphism via virtual methods. Note that all of these features can be approximated in C by manually following certain coding conventions, but by explicitly supporting them as part of the language, C++ makes them easier to use correctly and consistently.
Having done that, C++ then goes on to muddy the waters a bit, by making all of that new functionality available to structs as well as classes. (This is why the technical difference is so minor, as described in the first paragraph) However, I believe it is the case that when most programmers see a struct defined, they tend to have an implicit expectation that the struct is intended be used as a simple C-style data-storage/data-organization receptacle, whereas when they see a class, they expect it to include not just "some raw data" but also some associated business-logic, as implemented in the class's methods, and that the class will enforce its particular rules/invariants by requiring the calling code to call those methods, rather than allowing the calling code to read/write the class's member-variables directly. (That's why public member-variables are discouraged in a class, but less so in a struct -- because a public member-variable in a class-object contradicts this expectation, and violates the principle of least surprise).
While looking over some code, I ran into the following:
.h file
class ExampleClass
{
public:
// methods, etc
private:
class AnotherExampleClass* ptrToClass;
}
.cpp file
class AnotherExampleClass
{
// methods, etc
}
// AnotherExampleClass and ExampleClass implemented
Is this a pattern or something beneficial when working in c++? Since the class is not broken out into another file, does this work flow promote faster compilation times?
or is this just the style this developer?
This is variously known as the pImpl Idiom, Cheshire cat technique, or Compilation firewall.
Benefits:
Changing private member variables of a class does not require recompiling classes that depend on it, thus make times are faster, and
the FragileBinaryInterfaceProblem is reduced.
The header file does not need to #include classes that are used 'by value' in private member variables, thus compile times are faster.
This is sorta like the way SmallTalk automatically handles classes... more pure encapsulation.
Drawbacks:
More work for the implementor.
Doesn't work for 'protected' members where access by subclasses is required.
Somewhat harder to read code, since some information is no longer in the header file.
Run-time performance is slightly compromised due to the pointer indirection, especially if function calls are virtual (branch prediction for indirect branches is generally poor).
Herb Sutter's "Exceptional C++" books also go into useful detail on the appropriate usage of this technique.
The most common example would be when using the PIMPL pattern or similar techniques. Still, there are other uses as well. Typically, the distinction .hpp/.cpp in C++ is rather (or, at least can be) one of public interface versus private implementation. If a type is only used as part of the implementation, then that's a good reason not to export it in the header file.
Apart from possibly being an implementation of the PIMPL idiom, here are two more possible reason to do this:
Objects in C++ cannot modify their this pointer. As a consequence, they cannot change type in mid-usage. However, ptrToClass can change, allowing an implementation to delete itself and to replace itself with another instance of another subclass of AnotherExampleClass.
If the implementation of AnotherExampleClass depends on some template parameters, but the interface of ExampleClass does not, it is possible to use a template derived from AnotherExampleClass to provide the implementation. This hides part of the necessary, yet internal type information from the user of the interface class.
I am confused about such concepts when I discussed with my friend.
My friend's opinions are
1) abstraction is about pure virtual function.
2) interface is not member functions, but interface is pure virtual functions.
I found that in C++ primer, interface are those operations the data type support, so member functions are interface.
My opinions are
1) abstraction is about speration of interface and implementation;
2) member functions are interfaces.
So could anybody clarify these concepts for me?
1) the difference among abstraction, abstract data type and abstract class.
2) the difference between interface and member functions.
3) the difference between abstraction and encapsulation.
I think your main problem is that you and your friend are using two different definitions of the word "interface", so you're both right in different ways.
You are using "interface" in the everyday sense of "a defined way to inter-operate with something", as in "the interface between my computer and my keyboard is USB" or "the interface between the vacuum and the wall power is an outlet." In that sense, yes, methods (even concrete ones) are interfaces, since they define a way to inter-operate with an object. That's not to say that this is not applicable to software -- it is the sense of "interface" used in the term Application Programming Interface (API).
Your friend is using "interface" in the more specific object oriented programming jargon sense of "a separately defined set of operations that a class can choose to guarantee that it will support". Here, the defining characteristic of an "interface" is that it has no implementation of its own. A class is supposed to support an interface by providing an implementation of the methods defined by the interface. Since C++ has no explicit concept of an interface in this sense, the equivalent construct is a class with only pure virtual functions (aka an Abstract Data Type).
"Abstraction", on the other hand, is about many things and again you are both right. Abstraction in a general sense means being able to focus on higher-level concepts rather than lower level details. Encapsulation is a type of abstraction because its purpose is to hide the implementation details of the methods of a class; the implementation can change without the class definition changing. Pure virtual functions ("interfaces" in the OO-jargon sense) are another type of abstraction because they can, if used properly, hide not only the implementation but also the true underlying object type; the type being used can change so long as both types implement the same interface.
The same terms can be used for different things, which is what is happening here.
"Abstract" in C++ means a method that doesn't have an implementation at all (you can't instantiate an object with Abstract members.)
"Abstraction" is simply the concept of "modeling". Modelling is making something complex look simpler by ignoring some details. In programming, you want to break operations and concepts up into components, and for each component, abstract away details about external components that don't affect the current component's operation.
A programming "Interface" is a way of implementing "Abstraction". Rather than have all the source code and internal operations of a component, you only see the operations that are relevent to how you're using the object. An "Interface" in C++ is implemented by marking all methods on a class as "abstract" (also called "pure virtual".) That's done by putting an '= 0' after the method declaration but before the semicolon. The method has to be marked 'virtual' for this to be legal.
In other words, an abstract C++ class is one that has at least one pure virtual method, and an interface is implemented in C++ by making all member functions pure virtual.
Encapsulation is a fuzzy term, but to me it means a technique of implementing abstraction. It means "information hiding". You're hiding the internal details of how an object performs its "contract". The Contract is expressed through interfaces, which to my mind is a more powerful form of abstraction. Any C++ class with protected or private members uses encapsulation, but a class implementing only pure virtual methods is describing a contract, promising to deliver certain services for which you need to know absolutely nothing about how they are implemented or about other services the same object may implement.
The same object may fill several contracts, and by exposing multiple, disjoint interfaces, it doesn't force clients to know about all of the auxilliary functions of the object. For example, an object may be able to tell you a bank account balance, and it also may be able to be serialized/deserialized to a database. You could just have one class with all of those operations exposed as member functions. I prefer to define two interfaces, 'IDatabaseSerializable' and 'IBankAccount', and put the appropriate operations in the appropriate interfaces and derive from both interfaces in my implementation class. Then clients that only care about bank balances see as little extra information as possible, and the database only sees the operations that it cares about.
Virtual member functions (not neccessarily pure) in combination with inheritance are one way to express the concept of interfaces in C++, i.e. interfaces and methods are orthogonal concepts.
Another approach to interfaces in C++ is with generic code (i.e. templates), where you often don't expect any concrete type - instead you expect the type to have certain member functions with a certain semantic - if it doesn't you will get a compile error.
Some people call this concepts and you talk of a type modelling a certain concept. Concepts are not formally supported in C++ though, but libraries like Boost.ConceptCheck do a pretty good job of providing a substitute.
Abstraction means that someone can use your code without knowing about implementation details. The thing that makes this complicated is that things that are implementation details in one context may not be in others. An abstract data type is a data type that cannot be instantiated and only describes attributes of its subtypes. An abstract class is just something that's an abstract data type and a class.
An interface can be implicitly defined by a set of member functions (though to be a useful abstraction these should at least be virtual so that there is more than one possible implementation of the interface). It can also be defined explicitly as a class with only pure virtual functions (in C++) or an interface (in Java, C# and D).
Abstraction is when you don't have to know about the implementation details of something. Encapsulation is when you can't know about them. For example, a class that is otherwise well-designed from an OO perspective, but doesn't bother setting its member variables to private can still be a useful abstraction, but it is not encapsulated.
In what kind of scenarios would we declare a member function as a 'friend function' ?..What exact purpose does 'friend function' which defies one of central concept of 'Encapsulation' of OOP serve?
You would use a friend function for the same sort of reasons that you would use a friend class, but on a member function (rather than entire class) basis. Some good explanations are in this thread.
While friend functions and classes do violate encapsulation, they can be useful in some scenarios. For example, you may want to allow a test harness to access class internals to allow you to do whitebox testing. Rather than opening up the entire class to the test harness, you could open up a particular function which accesses the internals required by the test harness. While this still violates encapsulation, it's less risky than opening up the entire class.
Also see this article for some more information about friend classes and functions.
Friend functions and classes do not violate encapsulation when you are trying to build an abstraction or interface that must physically span multiple C++ classes or functions! That is why friend was invented.
Those types of cases don't come up often, but sometimes you are forced to implement an abstraction or interface with disparate classes and functions. The classic example is implementing some type of complex number class. The non-member operator functions are given friendship to the main complex number class.
I also recall doing this when programming with CORBA in C++. CORBA forced me to have separate classes to implement CORBA servants. But for a particular part of our software, I needed to marry these together as one interface. Friendship allowed these two classes to work together to provide a seamless service to one part of our software.
Having the ability to mark a particular member function on another class as a friend to your class may seem even stranger, but it is just a way of tightly controlling the friendship. Instead of allowing the entire other class "in" as your friend, you only allow one of its member functions access. Again, this isn't common, but very useful when you need it.
See C++ FAQ Lite:
Sometimes friends are syntactically better (e.g., in class Fred, friend functions allow the Fred parameter to be second, while members require it to be first). Another good use of friend functions are the binary infix arithmetic operators. E.g., aComplex + aComplex should be defined as a friend rather than a member if you want to allow aFloat + aComplex as well (member functions don't allow promotion of the left hand argument, since that would change the class of the object that is the recipient of the member function invocation).
Sometimes public/private/protected protection level is not quite enough for real world situations. So thus we give a small get-out clause that helps without having to make methods publicly accessible.
I personally use this the same way that Java uses the 'Package' protection level.
If I have a class in the same package that needs access I will consider using friend. If it is a class in another package then I will wonder why on earth is this other class needing access and look at my design.
One point that I find relevant: member classes have access to the private parts of the containing class. This may sometimes be a better alternative to "friend".
class A
{
private:
int b;
public:
class MemberNotFriend {
public:
static void test() {
A a;
a.b = 0;
}
};
};
void test()
{
A::MemberNotFriend::test();
}
Here is a simple, concrete example of how I am using a friend function:
I have a game where each sprite object stores its info like X,Y position as private members.
However, I wish to separate the game objects from the rendering: a game object does not need the exact details of how it is rendered. A game object only stores game state, and this game state may be rendered in a number of different ways.
Thus the game object class has a friend function: render(). The render() function is implemented outside the game object class, but it can access the X,Y position position membefrs as needed to render the game object.
As I understand, the pimpl idiom is exists only because C++ forces you to place all the private class members in the header. If the header were to contain only the public interface, theoretically, any change in class implementation would not have necessitated a recompile for the rest of the program.
What I want to know is why C++ is not designed to allow such a convenience. Why does it demand at all for the private parts of a class to be openly displayed in the header (no pun intended)?
This has to do with the size of the object. The h file is used, among other things, to determine the size of the object. If the private members are not given in it, then you would not know how large an object to new.
You can simulate, however, your desired behavior by the following:
class MyClass
{
public:
// public stuff
private:
#include "MyClassPrivate.h"
};
This does not enforce the behavior, but it gets the private stuff out of the .h file.
On the down side, this adds another file to maintain.
Also, in visual studio, the intellisense does not work for the private members - this could be a plus or a minus.
I think there is a confusion here. The problem is not about headers. Headers don't do anything (they are just ways to include common bits of source text among several source-code files).
The problem, as much as there is one, is that class declarations in C++ have to define everything, public and private, that an instance needs to have in order to work. (The same is true of Java, but the way reference to externally-compiled classes works makes the use of anything like shared headers unnecessary.)
It is in the nature of common Object-Oriented Technologies (not just the C++ one) that someone needs to know the concrete class that is used and how to use its constructor to deliver an implementation, even if you are using only the public parts. The device in (3, below) hides it. The practice in (1, below) separates the concerns, whether you do (3) or not.
Use abstract classes that define only the public parts, mainly methods, and let the implementation class inherit from that abstract class. So, using the usual convention for headers, there is an abstract.hpp that is shared around. There is also an implementation.hpp that declares the inherited class and that is only passed around to the modules that implement methods of the implementation. The implementation.hpp file will #include "abstract.hpp" for use in the class declaration it makes, so that there is a single maintenance point for the declaration of the abstracted interface.
Now, if you want to enforce hiding of the implementation class declaration, you need to have some way of requesting construction of a concrete instance without possessing the specific, complete class declaration: you can't use new and you can't use local instances. (You can delete though.) Introduction of helper functions (including methods on other classes that deliver references to class instances) is the substitute.
Along with or as part of the header file that is used as the shared definition for the abstract class/interface, include function signatures for external helper functions. These function should be implemented in modules that are part of the specific class implementations (so they see the full class declaration and can exercise the constructor). The signature of the helper function is probably much like that of the constructor, but it returns an instance reference as a result (This constructor proxy can return a NULL pointer and it can even throw exceptions if you like that sort of thing). The helper function constructs a particular implementation instance and returns it cast as a reference to an instance of the abstract class.
Mission accomplished.
Oh, and recompilation and relinking should work the way you want, avoiding recompilation of calling modules when only the implementation changes (since the calling module no longer does any storage allocations for the implementations).
You're all ignoring the point of the question -
Why must the developer type out the PIMPL code?
For me, the best answer I can come up with is that we don't have a good way to express C++ code that allows you to operate on it. For instance, compile-time (or pre-processor, or whatever) reflection or a code DOM.
C++ badly needs one or both of these to be available to a developer to do meta-programming.
Then you could write something like this in your public MyClass.h:
#pragma pimpl(MyClass_private.hpp)
And then write your own, really quite trivial wrapper generator.
Someone will have a much more verbose answer than I, but the quick response is two-fold: the compiler needs to know all the members of a struct to determine the storage space requirements, and the compiler needs to know the ordering of those members to generate offsets in a deterministic way.
The language is already fairly complicated; I think a mechanism to split the definitions of structured data across the code would be a bit of a calamity.
Typically, I've always seen policy classes used to define implementation behavior in a Pimpl-manner. I think there are some added benefits of using a policy pattern -- easier to interchange implementations, can easily combine multiple partial implementations into a single unit which allow you to break up the implementation code into functional, reusable units, etc.
May be because the size of the class is required when passing its instance by values, aggregating it in other classes, etc ?
If C++ did not support value semantics, it would have been fine, but it does.
Yes, but...
You need to read Stroustrup's "Design and Evolution of C++" book. It would have inhibited the uptake of C++.