Is it possible to separate class declaration from its definition? Of course it is, but what if I want to have an object of this class before the actual definition of it? Consider the following example:
class ID3_Reader{
public:
// code omitted for brevity
protected:
class Mp3_File;
Mp3_File mFile;
};
It's obvious that it will not compile. I would have to define the Mp3_File class inside the ID3_Reader class. It's not a problem when I have just two classes. What if there would be like five of them? My code would become pretty messy. To avoid this problem I would have to separate the class declarations from their definitions. How can I achieve that? Remember that I need an instance of the Mp3_File class inside the ID3_Reader class.
The reason why I'm using nested classes is because I don't want some other programmer to use the Mp3_File class. I used "protected" keyword because I will create classes based on the ID3_Reader class.
You can achive this by using a pointer like the other guys answered:
class Mp3_File; // forward declaration of class Mp3_File
class ID3_Reader{
public:
// code omitted for brevity
protected:
Mp3_File *mFile;
};
Or you can declare the constructor of class Mp3_File private and declare class ID3_Reader friend of class Mp3_File:
class Mp3_File {
Mp3_File() {} // constructor is private
friend class ID3_Reader;
};
class ID3_Reader{
public:
// code omitted for brevity
protected:
Mp3_File mFile;
};
auto main() -> int {
ID3_Reader r;
Mp3_File m; // Error Mp3_File constructor is private!
return 0;
}
Thus, other people won't be able to use Mp3_File while you can use it in the scope of class ID3_Reader.
It won't compile because the compiler doesn't know how much memory that Mp3_File class will use. If you change it to a pointer
class ID3_Reader{
public:
// code omitted for brevity
protected:
class Mp3_File;
Mp3_File *mFile;
};
that compiles just fine (a pointer has a fixed size - http://ideone.com/VmmXfK).
I suggest using a pointer instead of a complete member variable and initialize/deinitialize it in the ctor/dtor.
I don't see another way of doing it without changing the "nested classes" design.
You can achieve that by using pointers. Recall that although you must have a full class to define a variable, a simple forward declaration is good to define a pointer:
class ID3_Reader{
public:
// code omitted for brevity
protected:
class Mp3_File;
Mp3_File *mFile;
};
Unfortunately, this puts you on the hook for managing the memory for the nested class, but it does hide all of the internals of the class from outside programmers.
Instead of defining mFile as an instance of Mp3_File, define it as a pointer to an Mp3_File. That way you won't need to know the definition in the header file. Or better yet - use a smart pointer. You will then need to create the real instance by using new in the class constructor and delete it in ID3_Reader's destructor.
If you wish to stay with your current syntax to access mFile from outside of the class, dereference it inside the accessor function:
Mp3_File& getMp3(){ return *mFile; };
Then - if Mp3_File has an overloaded operator() (or any other overloaded operator as a matter of fact), you won't need to dereference it every time manually.
You can make your class a class template to work around this restriction: for class templates the definition of the nested type needs to be visible at instantiation time, not while looking at the definition of the class template. You might want to use a typedef to actually name the used instantiation to avoid the need to have a trailing <>. Here is a quick demo:
template <typename = void>
class ID3_ReaderT {
public:
// code omitted for brevity
protected:
class Mp3_File;
Mp3_File mFile;
};
typedef ID3_Reader<> ID3_Reader;
template <typename T>
class ID3_ReaderT<T>::Mp3_File {
};
int main()
{
ID3_Reader reader;
}
Of course, it still means that every user of ID3_Reader needs to see the definition of the nested type. If you want to avoid that, your option is on level indirection, i.e., using a pointer as was already stated by multiple answers.
Related
Here is a base class:
class Base
{
public:
int foo;
// ...
};
This class is declared in a header file that I cannot change because I don't have the rights to do so.
Here is a derived class:
class Derived : public Base
{
public:
// provide alias to Base::foo
// ...
};
Is there a way I can provide an alternate name that refers to Base::foo inside class Derived without using pointers or references?
In other words, is there any way to provide an alias without adding any extra class members to Derived?
Also, if conditional compilation directives can be avoided, that would be ideal.
No, there is no renaming feature (though there was some work done on such a feature in the early days but it was dropped).
There's no way to do what you want other than adding the desired name as a member to Derived, and forwarding it to the base class function. Note however that this can be inline and should be absorbed by the compiler so it won't hurt performance.
I have a base class Base defined in Base.h:
class Base
{ /* ... */ };
And a class template Child that derives from Base, defined in Child.h:
#include "Base.h"
template <class T>
class Child : public Base
{ /* ... */ };
Now I want to create some factory methods within the Base class, which should return a std::shared_ptr to the Child class. To avoid circular dependencies I tried to use a forward declaration instead. So Base.h now looks like this:
class Child; // new forward declaration
class Base
{
/* ... */
// new factory method
static std::shared_ptr<Base> CreateChildInt(int i = 0)
{
return std::make_shared<Child<int>>(i);
}
};
However, the definition of CreateChildInt() leads to the following compiler error:
"error C2947: expecting '>' to terminate template-argument-list, found '<'"
So is this even possible what I am trying to achieve?
If not, are there any workarounds / best practices for this approach?
EDIT:
The reason for why I want to put the factory method into the Base class instead of Child is the following. When I put the factory into Child I would need to call the factory method like this:
std::shared_ptr<Base> p = Child<int>::CreateChildInt(3);
However, I would like to omit the template type <int> in this call, thus:
std::shared_ptr<Base> p = Base::CreateChildInt(3);
Firstly, you declared a class, but Child that you define is actually a template. The correct way to declare a class template is:
template <class T>
class Child;
However, a correct forward declaration alone won't help you. The implementation of CreateChildInt::CreateChildInt must know the full definition of Child because it creates an instance of it. You can't define Child before Base either, because inheritance also depends on the full definition, so you'd end up with a cicrular dependency.
Solution: Forward declare Child, then define Base but don't define Base::CreateChildInt inline, then define Child and finally define Base::CreateChildInt.
PS. I find it dubious from OOP perspective that the implementation of the base class member function depends on the child class. I recommend that you consider re-designing your approach.
Sometimes, we need to provide a specific constructor solely for test usage. How can we force such constructor is solely used in test code, nowhere else.
I just wonder if this is achievable in c++11/14. e.g.,
class A {
public:
A() = default; // used only in test code
}
class A_Test : public ::testing::Test {
private:
A a; // it is ok.
};
class A_Production {
private:
A a; // compiler error
}
I could imagine to use friend decorator and put the specific constructor in protected to limit the access. but there are other existing friends in legacy code too. Is it possible to make a custom specifier like protected in c++1x?
any ideas?
You could use the Passkey Idiom:
Instead of a direct friendship, you limit the access to A from A_Test through the indirection provided by ConstructorKey, which A uses in its interface where it wants the friends of ConstructorKey to access.
class A {
class ConstructorKey {
friend class A_Test;
private:
ConstructorKey() {};
ConstructorKey(ConstructorKey const&) = default;
};
public:
// Whoever can provide a key has access:
explicit A(ConstructorKey); // Used only in test code
};
class A_Test : public ::testing::Test {
private:
A a {ConstructorKey{}}; // OK
};
class A_Production {
private:
A a {ConstructorKey{}}; // Compiler error
};
I can think of several ways to do that.
Make the constructor protected, with only the test subclass using it.
Add a forward declaration to some dummy class, class TestClassThatShouldNotBeUsedInProductionCode;, then declare a constructor that takes a reference to this class as a parameter:
A::A( /* other constructor arguments */,
const TestClassThatShouldNotBeUsedInProductionCode &)
This constructor can simply ignore this parameter altogether. Your test module can define this dummy, empty class: class TestClassThatShouldNotBeUsedInProductionCode {};, and be able to construct your A class using it. Only your test module would be able to use this constructor, then, and its name makes it pretty clear what the purpose of this is. There isn't really any way to define certain translation units as "real" code versus "test" code, in C++, you just want to implement a clear policy that would be hard to violate accidentally.
Some variations are possible, such as using an inner class instead of forward-declaring a standalone class. The inner class could only be instantiated only by the test code.
As an alternative, in the cpp file that does the testing of A:
#define private public
#include "ClassA.h"
// ready for testing :)
Is there a way to explicitly declare a base class as abstract in C++?
I know that I can create a pure virtual function in the class which will implicitly declare a class as abstract. However, I don't want to have to create a dummy function just to define in in derived classes.
I could also make the constructor protected, which would prevent the instantiation of the object, but that doesn't actually mark the class as abstract.
So, is there a way to do this? (I am using C++11, if that added a way to do this, but I didn't find anything that looked right)
You can make the destructor pure-virtual. Since you always need a destructor, there's no additional mental cost:
struct Foo
{
virtual ~Foo() = 0;
};
inline Foo::~Foo() { }
(You do of course need an implementation of the destructor, so you have to provide one out-of-line.)
You can still make the destructor protected, which is good practice following the "make non-leaf classes abstract" rule.
Example:
struct Bar : Foo { };
// Foo f; // Error, Foo is abstract
Bar b; // OK
I like Kerrek's answer. That way the class cannot be instantiated and therefore is abstract.
However, it still isn't obviously clear that the class is abstract unless you scan through the entire declaration of the class and see that the destructor is virtual.
Another idea I had is you could create a pre-processor definition for the word "abstract" using #define. This way you could do something like the following:
abstract struct Foo {};
which would be no different than
struct Foo {};
The problem I see with this is that this doesn't force the class to be abstract, so you could use a macro to also declare the virtual destructor. Something like:
#define ABSTRACT_CLASS(class_name) \
class class_name { \
virtual ~class_name() = 0; //
And then use it like so:
ABSTRACT_CLASS(Foo) {
// class declaration
};
Which would be turned into:
class foo {
virtual ~class_name() = 0; // {
// class declaration
};
Disclaimer: My macro might be slightly off. I'm not sure if it'll actually paste class_name with the ~ and the () touching the variable name. Also, I'm not sure if I'd do this myself, it's not the most beautiful solution, especially commenting out the brace since that wouldn't work if you put it on the next line. But you asked how you could mark something as abstract and I gave it to you!
Is there a way to explicitly declare a base class as abstract in C++?
No, there is not. A class is abstract only if it has at least one abstract method declared in it. If you do not want your base class to be instantiated directly, then a protected constructor is a good choice.
I know the questions seems ambiguous, but I couldn't think of any other way to put it, but, Is it possible to do something like this:
#include<iostream>
class wsx;
class wsx
{
public:
wsx();
}
wsx::wsx()
{
std::cout<<"WSX";
}
?
Yes, that is possible. The following just declares wsx
class wsx;
That kind of declaration is called a forward declaration, because it's needed when two classes refer to each other:
class A;
class B { A * a; };
class A { B * b; };
One of them needs to be forward declared then.
In your example,
class wsx; // this is a class declaration
class wsx // this is a class definition
{
public:
wsx();
}
So yes, by using class wsx; it is possible to declare a class without defining it. A class declaration lets you declare pointers and references to that class, but not instances of the class. The compiler needs the class definition so it knows how much memory to allocate for an instance of the class.
This is the definition of the class
class wsx
{
public:
wsx();
}
This is the definition of the constructor
wsx::wsx()
{
std::cout<<"WSX";
}
THis is a forward declaration that says the class WILL be defined somewhere
class wsx;
Yes. But it is not possible to define a class without declaring it.
Because: Every definition is also a declaration.
You did define the class. It has no data members, but that's not necessary.
I'm not sure what you mean. The code you pasted looks correct.