Internal class declaration [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Pros and cons of using nested C++ classes and enumerations?
Consider the following declaration.
class A {
public:
class B{
};
};
Nothing special.
But what are the benefits of this?
What reasons may there be for putting one class inside of another?
There is no inheritance benefit between both classes.
If B is put inside of A for its private names sharing, then A is for B just a namespace, and there is reason to make B private, too.
What do you think about this?

Conceptually, it lets the programmer(s) know that class B relates specifically to class A. When you use class B outside of class A, you must use the type as A::B, which reminds you, every time, that B is related to A. This doesn't add any functionality, but shows a relationship.
Similarly, you don't have to use inheritance/composition, or classes at all. You can more or less simulate classes in C just by using structs and functions. It's just a way to keep the code cleaner and more straightforward and let the programmer relate the code to the design more easily. Classes accomplish this much more than public subclasses do, but that's just an example.
If it's a private/protected subclass (which I see it isn't in your example), then that obviously limits that class to the implementation of that class and that class's children, which might be desired (again design-wise) if the only use case of that class is in the implementation of that class (and possibly its children).

Benefit 1: The namespace aspect
Indeed, A provides a namespace for B, and this can help us structure our code much better. Consider a concrete example with vector for A, and iterator for B. Arguably,
class vector {
public:
class iterator { /*...*/ };
iterator begin() { /*...*/ }
};
is easier to type, to read, and to understand than
class vector_iterator {
/*...*/
};
class vector {
public:
vector_iterator begin() { /*...*/ }
};
Observe, in particular:
When the two classes (vector and iterator) depend on each other, i.e. use each other's members, the second version above would require one of the two to be forward-declared, and in some cases mutual type-dependencies might lead to unresolvable situations. (Using nested classes, it is much easier to avoid such problems, because within most parts of the nested class definition, the outer class is considered completely-defined. This is due to §9.2/2.)
You may very well have many other data types that maintain their own iterator, e.g. linked_list. Using the second version above, you'd need to define linked_list_iterator as a separate class. Class names would get ever longer and complicated the more of these 'dependent' types and alternative types you added.
Benefit 2: Templates
Continuing the example above, consider now a function template that takes a container (such as vector and linked_list defined above) as arguments and iterates over them:
template <typename Container>
void iterate(const Container &container) {
/*...*/
}
Inside this function, you'd obviously very much like to use the iterator type of Container. If that is a nested type, it's easy:
typename Container::iterator
But if it isn't, you would have to take the iterator type as a separate template parameter:
template <typename Container, typename Iterator>
void iterate(const Container &container) {
/*...*/
Iterator it = container.begin();
/*...*/
}
And if that iterator type does not appear among the function arguments, the compiler could not even guess the type. You'd have to explicitly add it in angle brackets each time you call the iterate function.
Final notes: None of this has much to do with whether the nested class is declared as public or private. My examples above suggest a situation in which a public nested type is clearly preferrable, because I suppose the iterator type should be able to be used outside the container class.

What reasons may be for putting one class inside of another one?
If you need to restrict the scope of B to only available for A, then internal class definition helps. Because it restricts the class scope to local.This is call scope localization.These are in more generic term called inner class declaration. Check this link.
This stackoverflow question helps you understand more.

Related

c++ function cannot derive template for child class of base class with templates

I am somewhat new to templates and I don't understand how the compiler derives the templates for child classes when I inherit from the base class in a way where I set the templates.
I am creating a genetic algorithm base class for which I have written an abstract base class for the individuals of a population. I want to have a general definition so I use templates to define the fenotype and genotype:
template<typename T, typename S>
class individual {
public:
individual(S& fenotyp, T& genotyp) :
fenotype(fenotyp), genotype(genotyp) {}
...
S fenotype;
T genotype;
...
};
When the individuals are bitstrings, I have the following child class:
class bitstring_individual : public individual<boost::dynamic_bitset<>,
boost::dynamic_bitset<>> {
public:
using individual::individual;
...
};
Now I no longer have to work with template brackets anymore. Further down the line, I have a function that given a population std::vector<individual<T,S>>, returns the half with the highest fitness. This works on any type of individual so we can keep the definition general:
template<typename T, typename S>
std::vector<individual<T,S>> select_best_half(std::vector<individual<T,S>> parents,
std::vector<individual<T,S>> children) {
...
}
However, if I call this function I get error: no matching function for call to select_best_half(...) and the compiler says template argument deduction/substitution failed: and mismatched types ‘individual<T, S>’ and ‘bitstring_individual'.
In the definition of bitstring_individual we see that:
bitstring_individual : individual<boost::dynamic_bitset<>,boost::dynamic_bitset<>>
so why does the compiler not understand that the templates should be boost::dynamic_bitset<>? Can someone help me understand how the compiler tackles this inheritance and how can I fix it?
(using bitset = boost::dynamic_bitset)
Your bitstring_individual is not the same as individual<bitset, bitset>, and the compiler rightfully does not recognize them as such. One inherits the other, yes, but that does not make them interchangeable everywhere - in particular when used as template arguments.
In short: vectors (and other containers) of different (even polymorphically related) types are not covariant. Just like you cannot pass a std::vector<int> to a function expecting a std::vector<long> you cannot pass a std::vector<bitstring_individual> where a std::vector<individual<bitset, bitset>> is expected.
Note: Yes, they are different conversions, but the idea is the same.
Imagine that sizeof(individual<bitset, bitset>) = 32 and that bitstring_individual adds some members so that sizeof(bitstring_individual) = 48. If the compiler deduced T = S = bitset, then it would generate a method signature containing std::vector<individual<bitset, bitset>>, so a vector whose elements have size 32. But when you try to call it, you are passing a vector whose elements have size 48. Those vectors are not covariant, which would invariably lead to problems.
If you want your concrete individuals to have no other functionality than what the templated base class provides, just do this:
using bitstring_individual = individual<bitset, bitset>;
Otherwise, your vectors cannot store the individuals directly - you would have to use something like std::vector<std::shared_ptr<individual<T, S>>> (alternatively unique_ptr or ref instead of shared_ptr) for all population vectors.
Your question actually deals with covariance and contravariance of (certain) types in C++. Even if you were to "hard-code" your template parameters, i.e. have:
using i_bs_bs = individual<bitset, bitset>;
using std::vector;
class bitstring_individual : public i_bs_bs { ... };
vector<bsi> select_best_half(vector<i_bs_bs> parents, vector<i_bs_bs> children) {
...
}
You'd still get an error passing a vector<bitstring_individual> to select_best_half(). Why? Because, in C++ std::vector<T> is not a covariant type constructor.
To take the the example from the linked-to Wikipedia page, Suppose your inheriting classes were Animal (base class) and Cat (derived class). In C++, you can't add an Animal to a vector of Cats. All elements of that vector need to be Cats. Similarly, and as #MaxLanghof's answer explains, you can't add a bitstring_individual to a vector whose elements are of bitstring_individual's base type. Any special behavior necessary for handling bitstring_individual would simply not apply to the elements of a vector<i_bs_bs>.

Avoiding proliferation of templates

I am working on a fairly tightly coupled library which up until now has explicitly assumed all computations are done with doubles. I'm in the process of converting some of the core classes to templates so that we can start computing with std::complex<double>. I've templated about 10 of our classes so far have noticed a tendency toward proliferation of templates. As one class becomes templated, any other class that uses the templated class appears to need templating as well. I think I can avoid some of this proliferation by defining abstract base classes for my templates so that other classes can just use pointers to the abstract class and then refer to either a double or std::complex<double> version of the derived class. This seems to work on at the header level, but when I dive into the source files, the templated class will often have functions which compute a value or container of values of type double or std::complex<double>. It seems like a waste to template a whole class just because a couple of lines in the source file are different because of some other classes return type.
The use of auto seems like a possible way to fix this, but I'm not 100% sure it would work. Suppose I have an abstract base class AbstractFunction from which Function<Scalar> derives, where Scalar can be double or std::complex<double>. Now suppose we have two member functions:
virtual Scalar Function<Scalar>::value(double x);
virtual void Function<Scalar>::values(std::vector<Scalar> &values, std::vector<double> x);
And suppose I have some other class (that I don't want to template) with a member function that calls one of these.
// populate double x and std::vector<double> xs
auto value = functionPtr->value(x);
std::vector<auto> values;
functionPtr->values(values, xs);
// do something with value and values
where functionPtr is of type std::shared_ptr<AbstractFunction>.
I could see auto working for the first case, but I don't believe I could construct a vector of auto to be filled with the second one. Does this necessitate making the calling class a template? Can someone recommend another strategy to cut down on the proliferation of templates?
I think you are already wrong in assuming that the first use-case is going to work. If you have an abstract base class, then either value is a member of it and you can call it through std::shared_ptr<AbstractFunction> or value is not a member of it and only available if you know the derived class' type. In the first case, the AbstractFunction::value method must have a fixed return type, it can not depend on Scalar, which is the template parameter of the derived class.
That said: In my experience the two concept often don't mix well. You either want to create an abstract base class with the full interface or you want a template. In the latter case, there is often no need / no benefit for having an abstract base class. It then follows that also the code using your template works with templates.
What might help you is to "export" the template parameter from Function, i.e.
template<typename T>
class Function
{
public:
using value_type = T;
value_type value() const;
// ...
};
and in other parts of the code, use a template which takes any T which behaves like Function if you don't want to directly write out (and limit yourself) to Function:
template<typename T>
void something( const std::shared_ptr<T>& functionPtr )
{
// ignoring where x comes from...
using V = typename T::value_type;
V value = functionPtr->value(x);
std::vector<V> values;
functionPtr->values(values, xs);
}
Note that this is just one option, I don't know if it is the best option for your use-case.

Hold any kind of C++ template class in member variable

I have got two classes.
The first class (A) is builded with an template.
template <class T>
class A
{
public:
T value;
};
The second class (B) should have an object of class A as member variable. Like this:
class B
{
public:
A<int> value;
};
But now i want to use any kind of template-class in class A. Not only int.
Apparent I can't declare a (member-)variable which contains any kind of a class.
So, I need something like this:
class B
{
public:
A<*> value;
};
Is there any (clean) solution for this problem?
-- Greeting from Germany, Bastian
You cannot have a single class B with "any" member object, because B has to be a well-defined class, and A<T> is a different type for different types T. You can either make B a template itself:
template <typename T>
class B
{
A<T> value;
};
or you can take a look at boost::any, which is type-erasing container for arbitrary types (but making use of it requires a certain amount of extra work). The any class only works for value types, though, it's not completely arbitrary.
The simplest solution would be to make all A variants ineherit from a common interface, even if it's empty :
class IA{}
template <class T>
class A : public IA
{
public:
T value;
};
class B
{
public:
IA* value;
};
Now, the associated costs:
interactions with value are limited to the IA interface;
if you try to cast to get the real type, that mean that you know the real type, so it's of no use and make A type a parameter of B becomes really easier to use.
there are runtime costs associated to runtime inheritance
Advantage :
it's easily understood by other developers
it naturally limit the types possible to some specific ones
it don't use boost (sometimes, you just can't)
So to do better there are other less simple solutions but that are simple enough to be used :
If you can use boost, boost::any, boost::variant and boost::mpl might be base of solutions.
Boost any can be used as a safe replacement to void*. The only problem with this is that you can have ANY type, like if the type was a template parameter of the B class.
Boost variant might be used successfully if you know all the types that A can be.
MPL might be helpful if you just want to set a list of possible types and make sure your members apply only to them. You can do a ton of things with MPL so it really depends on your exact needs.
You've got two choices, I think. The first is to parameterize your class over the type parameters of the instance variables:
template <class T> struct B
{
A<T> value;
};
The other option is to declare value as a void* pointer. (But that's probably not what you want).
yes, it's already been done. boost::any.
I think it helps to understand, that templated classes create an entirely new and seperate class for every type you use with it. For instance, Vector<int> and Vector<float> are as separate as the classes VectorInt and VectorFloat.
For class B, you are basically asking that the value variable either be A<int> or A<float>, which is the same as saying you want value to either be a "A_int" or "A_float". And to accomplish that you... well, use another template!

Why are C++ classes allowed to have zero data members?

question about c++
why minimal number of data members in class definition is zero
i think it should be one , i.e pointer to virtual table defined by compiler
thanks a lot
It is often useful to have a class with no data members for use in inheritance hierarchies.
A base class may only have several typedefs that are used in multiple classes. For example, the std::iterator class template just has the standard types defined so that you don't need to define them in each iterator class.
An interface class typically has no data members, only virtual member functions.
A virtual table has nothing to do with the data members of a class.
I’m working on a library that sometimes even uses types that – gasp! – aren’t even defined, much less have data members!
That is, the type is incomplete, such as
struct foobar;
This is used to create an unambiguous name, nothing more.
So what is this useful for? Well, we use it to create distinct tags, using an additional (empty, but fully defined) type:
template <typename TSpec>
struct Tag {};
Now you can create distinct tags like so (yes, we can declare the type inside the template argument list, we do not need to declare it separately):
using ForwardTag = Tag<struct Forward_>;
using RandomAccessibleTag = Tag<struct RandomAccessible_>;
These in turn can be used to disambiguate specialized overloads. Many STL implementations do something similar:
template <typename Iter>
void sort(Iter begin, Iter end, RandomAccessibleTag const&) …
Strictly speaking, the indirect route via a common Tag class template is redundant, but it was a useful trick for the sake of documentation.
All this just to show that a (strict, static) type system can be used in many different ways than just to bundle and encapsulate data.
Well, actually C++ mandates that all classes must occupy some space (You need to be able to generate a pointer to that class). They only need a pointer to a vtable though, if the class is polymorphic. There's no reason for a vtable at all in a monomorphic class.
Another use of a class with no data-members is for processing data from other sources. Everything gets passed into the class at runtime through pointers or references and the class operates on the data but stores none of it.
I hadn't really thought about this until I saw it done in a UML class I took. It has it's uses, but it does usually create coupled classes.
Because classes are not structures. Their purpose, contrary to popular belief, is not to hold data.
For instance, consider a validator base class that defines a virtual method which passes a string to validate, and returns a bool.
An instance of a validator may refuse strings which have capital letters in them. This is a perfect example on when you should use a class, and by the definition of what it does, there's clearly no reason to have any member variables.
question about c++ why minimal number of data members in class definition is zero
It is zero because you have various cases of classes that should have no members:
You can implement traits classes containing only static functions for example. These classes are the equivalent of a namespace that is also recognizable as a type. That means you can instantiate a template on the class and make sure the implementation of that template uses the functions within the class. The size of such a traits class should be zero.
Example:
class SingleThreadedArithmetic
{
static int Increment(int i) { return ++i; }
// other arithmetic operations implemented with no thread safety
}; // no state and no virtual members -> sizeof(SingleThreadedArithmetic) == 0
class MultiThreadedArithmetic
{
static int Increment(int i) { return InterlockedIncrement(i); }
// other arithmetic operations implemented with thread safety in mind
}; // no state and no virtual members -> sizeof(MultiThreadedArithmetic) == 0
template<class ThreadingModel> class SomeClass
{
public:
void SomeFunction()
{
// some operations
ThreadingModel::Increment(i);
// some other operations
}
};
typedef SomeClass<SingleThreadedArithmetic> SomeClassST;
typedef SomeClass<MultithreadedArithmetic> SomeClassMT;
You can define distinct class categories by implementing "tag" classes: classes that hold no interface or data, but are just used to differentiate between separate "logical" types of derived classes. The differentiation can be used in normal OOP code or in templated code.
These "tag" classes have 0 size also. See the iterators tags implementation in your current STL library for an example.
I am sure there are other cases where you can use "zero-sized" classes.

What is wrong with this inheritance?

I just don't get it. Tried on VC++ 2008 and G++ 4.3.2
#include <map>
class A : public std::multimap<int, bool>
{
public:
size_type erase(int k, bool v)
{
return erase(k); // <- this fails; had to change to __super::erase(k)
}
};
int main()
{
A a;
a.erase(0, false);
a.erase(0); // <- fails. can't find base class' function?!
return 0;
}
When you declare a function in a class with the same name but different signature from a superclass, then the name resolution rules state that the compiler should stop looking for the function you are trying to call once it finds the first match. After finding the function by name, then it applies the overload resolution rules.
So what is happening is the compiler finds your implementation of erase(int, bool) when you call erase(0), and then decides that the arguments don't match.
1: You need to be extremely careful when deriving from C++ standard library containers. It can be done, but because they don't have virtual destructors and other such niceties, it is usually the wrong approach.
2: Overload rules are a bit quirky here. The compiler first looks in the derived class, and if it finds any overload with the same name, it stops looking there. It only looks in the base class if no overloads were found in the derived class.
A simple solution to that is to introduce the functions you need from the base class into the derived class' namespace:
class A : public std::multimap<int, bool>
{
public:
using std::multimap<int, bool>::erase; // Any erase function found in the base class should be injected into the derived class namespace as well
size_type erase(int k, bool v)
{
return erase(k);
}
};
Alternatively, of course, you could simply write a small helper function in the derived class redirecting to the base class function
You've hidden the base class's erase member function by defining a function in the derived class with the same name but different arguments.
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9
First of all, you should never derive from STL containers, because no STL containers define a virtual destructor.
Second of all, see Greg's answer about inheritance.
Think whether you really want to inherit from std::map. In all the time I've written code, and that's longer than STL exists, I've never seen an instance where inheriting from a std::container was the best solution.
Specifically, ask yourself whether your class IS a multimap or HAS a multimap.
Others have answered how to resolve the syntax problem and why it can be dangerous to derive from standard classes, but it's also worth pointing out:
Prefer composition to inheritance.
I doubt you mean for 'A' to explicitly have the "is-a" relationship to multimap< int, bool >. C++ Coding Standards by Sutter/Alexandrescu has entire chapter on this (#34), and Google points to many good references on the subject.
It appears there is a SO thread on the topic as well.
For those that use Effective C++ as a C++ programming reference, this issue is covered in Item 33 (Avoid hiding inherited names.) in the book.
I agree with others' comments that you need to be very careful inheriting from STL classes, and it should almost always be avoided.
However, this problem could arise with some other base class from which it's perfectly sensible to inherit.
My question is: why not give your 2-argument function a different name? If it takes different arguments, presumably it has a slightly different meaning? E.g. erase_if_true or erase_and_delete or whatever the bool means.
To replace __super in a portable way, define a typedef at the top of your class like this:
typedef std::multimap<int, bool> parent;
public:
size_type erase(int k, bool v)
{
return parent::erase(k);
}
It does not need to be "parent" of course. It could be any name you like, as long as it is used consistently throughout your project.