Related
I am relatively new to c++. So apologies if this q is naive. But I couldn't get an answer so asking it here.
I have an existing .cpp file (one.cpp) which has a class (class A) defined inside it(one.cpp does not have corresponding one.h). Now I want another class (class B) in another file (two.h) to extend class A. But as A is not inside a header, I cannot do #include one.h
I am thinking of creating one.h, but class A is huge, so trying to avoid it.
Is there an easier way to do it?
In order for the linker to be able to identify class A in two.h, it would need reference to that class through a header file. As far as I know, there's no way around that.
Keep in mind that you only need to put the function prototypes in the header, not the actual definition.
You can include one.cpp in your two.h file like this #include "one.cpp". However this is considered bad practice. What you should do is create a header file for your class A.
Keep in mind that you don't have to actually implement the class in the header file.
I encountered a problem in opensource c++ code. The following is a small and simplified version to describe my problem:
#include <iostream>
using namespace std;
#define TOGETHER2(a,b) a ## b
#define TOGETHER(a,b) TOGETHER2(a,b)
#define GENERATE_NAME(a) TOGETHER(a,__COUNTER__)
#define GENERATE GENERATE_NAME(__seed_)
class base{
}b;
class GENERATE:public base{
}GENERATE;
class GENERATE:public base{
}GENERATE;
class GENERATE:public base{
}GENERATE;
class GENERATE:public base{
}GENERATE;
int main(){
return 0;
}
As we can see, the author defines several classes, which inherites a base class. But the author do not care about the names of the classes. So I wonder how can I use those classes without specifying their names?
Is this a kind of design pattern in c++ that I don't know?
Thank you :)
I want to add my guesses to make the question clear.
My guesses:
The names of these classes are generated from __seed_, but when I search through the files, I can not find other references to __seed_, So I am sure The author did not use the names __seed_1, __seed_2 to create classes. (Actually the author said the the comments that she did not care about the names of the classes)
I also guessed that the author may have used those classes through the interface defined in the base class(virtual function). To do that, the author still needed to create these classes, but as I mentioned I could not find __seed_ in other parts of the code, So the author couldn't create classes, and therefore virtual function do not work either.
Actually, I tried remove these class definitions, and strangely the code compiles correctly. However, It lost some of functionalities, but It did not just core dump. It could still finish some tasks successfully u
So, do anyone know:
How can we use those classes without specifying their names?
Is this design a certain kind of design pattern?
In which situation should we define class without caring about their names?
As I mentioned, I removed some part of the code, and It compiled. How could this happen? I mean, Since I remove many classes from the source code, then If other parts of the code references those classes, the source can not compile. And If it compiles, Can I just conclude that those classes are not needed?
ADDED:
As some of you recommended,
the full source code is here: MIT Cryptdb. In the file ./main/rewrite_const.cc, the author used macro ANON(lion 25) to define many classes without caring about their names.
Really appreciate your help :)
I recommend you to edit the code and add names for the classes. This is a strange design pattern, and I wouldn't recommend you to use such pattern for anything, unless you want to prevent others from using your classes.
If the author wants you to use those classes, there is probably some way you can use them without editing the code and adding the names. You should consult the documentation for this.
As I mentioned, I removed some part of the code, and It compiled. How could this happen? I mean, Since I remove many classes from the source code, then If other parts of the code references those classes, the source can not compile. And If it compiles, Can I just conclude that those classes are not needed?
All those generated classes are derived from the base class. So if you remove one class, all classes that come after it receive a new generated name. If the code now compiles, it means the other code is only calling the methods that are part of the base class. But the other code is now using other classes than what it originally used, which causes the errors you observe.
Consider this:
Initially the generated classes have names A, B, and C.
You remove class A.
Now the generated classes have names A and B. Class named C no longer exists, so the code that uses it should no longer compile. And the code that used class A and B before, it is now using the classes that used to be B and C.
These classes do have names. Only that these names are not revealed to the human reader and are not specified before the preprocessor has run. (If you run the compiler with option -E, it will only run the preprocessor stage and output the code as the compiler proper sees it, including the class names.)
AFAIK, there is no sensible reason to hide the names in this way. If the author doesn't want humans to write code that uses these classes, then there are other ways.
Defining such names in a header file to be included by the user implies that they cannot be used from within the library other than via polymorphism (because the library cannot know their names). This is the reason why removing them made no difference regarding compilation.
In C++, classes are usually declared like this:
// Object.h
class Object
{
void doSomething();
}
// Object.cpp
#include "Object.h"
void Object::doSomething()
{
// do something
}
I understand that this improves compile time because having the class in one file makes you recompile it whenever you change either the implementation or the interface (see this).
However, from and OOP point of view, I don't see how separating the interface from the implementation helps. I've read a lot of other questions and answers, but the problem I have is that if you define the methods for a class properly (in separate header/source files), then how can you make a different implementation? If you define Object::method in two different places, then how will the compiler know which one to call? Do you declare the Object::method definitions in different namespaces?
Any help would be appreciated.
If you want one interface and multiple implementations in the same program then you use an abstract virtual base.
Like so:
class Printer {
public:
virtual void print_string(const char *s) = 0;
virtual ~Printer();
};
Then you can have implementations:
class EpsonPrinter : public Printer {
public:
void print_string(const char *s) override;
};
class LexmarkPrinter : public Printer {
public:
void print_string(const char *s) override;
};
On the other hand, if you are looking at code which implements OS independence, it might have several subdirectories, one for each OS. The header files are the same, but the source files for Windows are only built for Windows and the source files for Linux/POSIX are only built for Linux.
However, from [an] OOP point of view, I don't see how separating the interface from the implementation helps.
It doesn't help from an OOP point of view, and isn't intended to. This is a text inclusion feature of C++ which is inherited from C, a language that has no direct support for object-oriented programming.
Text inclusion for modularity is a feature borrowed, in turn, from assembly languages. It is almost an antithesis to object-oriented programming or basically anything that is good in the area of computer program organization.
Text inclusion allows your C++ compiler to interoperate with ancient object file formats which do not store any type information about symbols. The Object.cpp file is compiled to this object format, resulting in an Object.o file or Object.obj or what have you on your platform. When other parts of the program use this module, they almost solely trust the information that is written about it in Object.h. Nothing useful emanates out of the Object.o file except for symbols accompanied by numeric information like their offsets and sizes. If the information in the header doesn't correctly reflect Object.obj, you have undefined behavior (mitigated, in some cases, by C++'s support for function overloading, which turns mismatched function calls into unresolving symbols, thanks to name mangling).
For instance if the header declares a variable extern int foo; but the object file is the result of compiling double foo = 0.0; it means that the rest of the program is accessing a double object as an int. What prevents this from happening is that Object.cpp includes its own header (thereby forcing the mismatch between the declaration and definition to be caught by the compiler) and that you have a sane build system in place which ensures that Object.cpp is rebuilt if anything touches Object.h. If that check is based on timestamps, you must also have a sane file system and version control system that don't do wacky things with timestamps.
If you define Object::method in two different places, then how will the compiler know which one to call?
It won't, and in fact you will be breaking the "One Definition Rule" if you do this, which results in undefined behavior, no diagnostic required, according to the standards.
If you want to define multiple implementations for a class interface, you should use inheritance in some way.
One way that you might do it is, use a virtual base class and override some of the methods in different subclasses.
If you want to manipulate instances of the class as value types, then you can use the pImpl idiom, combined with virtual inheritance. So you would have one class, the "pointer" class, which exposes the interface, and holds a pointer to an abstract virtual base class type. Then, in the .cpp file, you would define the virtual base class, and define multiple subclasses of it, and different constructors of the pImpl class would instantiate different of the subclasses as the implementation.
If you want to use static polymorphism, rather than run-time polymorphism, you can use the CRTP idiom (which is still ultimately based on inheritance, just not virtual inheritance).
I know it's possible to do class implementation in more than one file(yes, I know that this is bad idea), but I want to know if it's possible to write class definition in separate files without getting a redefinition error (maybe some tricks, or else...)
No, not the same class, but why would you?
You could define two classes with the same name in the same namespace (the same signature! That will actually be the same class at all, just defined in two ways) in two different header files and compile your program, if your source files don't include both headers. Your application could even be linked, but then at runtime things won't work as you expect (it'll be undefined behavior!), unless the classes are identical.
See Charles Bailey's answer for a more formal explanation.
EDIT:
If what you want is to have a single class defined by more than one file, in order to (for example) add some automatically generated functions to your class, you could #include a secondary file in the middle of your class.
/* automatically generated file - autofile.gen.h */
void f1( ) { /* ... */ }
void f2( ) { /* ... */ }
void f3( ) { /* ... */ }
/* ... */
/* your header file with your class to be expanded */
class C
{
/* ... */
#include "autofile.gen.h"
/* ... */
};
Not as nice and clean as the partial keyword in C#, but yes, you can split your class into multiple header files:
class MyClass
{
#include "my_class_aspect1.h"
#include "my_class_aspect2.h"
#include "my_class_aspect3.h"
};
#include "my_class_aspect1.inl"
#include "my_class_aspect2.inl"
#include "my_class_aspect3.inl"
Well sort of ...
If you have 1 header file as follows
ClassDef1.h:
class ClassDef
{
protected:
// blah, etc.
public:
// more blah
and another as follows
ClassDef2.h:
public:
// Yet more blah.
};
The class will effectively have been defined across 2 files.
Beyond that sort of trickery .. AFAIK, no you can't.
Yes, you can. Each definition must occur in a separate translation unit but there are heavy restrictions on multiple definitions.
Each definition must consist of the same sequence of tokens and in each definition corresponding names must refer to the same entity (or an entity within the definition of the class itself).
See 3.2 [basic.def.odr] / 5 of ISO 14882:2003 for full details.
Yes. Usually, people put the declaration part in .h file and then put the function body implementations in .cpp file
Put the declarations in a .h file, then implement in as many files as you want, but include the .h in each.
But, you cannot implement the same thing in more than one file
I know this is a late post, but a friend just asked me a similar question, so I thought I would post our discussion:
From what I understand you want to do ThinkingStiff, it's not possible in C++. I take it you want something like "partial class" in C#.
Keep in mind, "partial class" in .NET is necessary so you don't have to put your entire implementation in one big source file. Unlike C++, .NET does not allow your implementation to be separate from the declaration, therefore the need for "partial class". So, Rafid it's not a nice feature, it's a necessary one, and a reinvention of the wheel IMHO.
If your class definition is so large you need to split it across more than one source file, then it can probably be split into smaller, decoupled classes and the primary class can use the mediator design pattern that ties them all together.
If your desire is to hide private members, such as when developing a commercial library and you don't wish to give away intelectual property (or hints to that affect), then you can use pure abstract classes. This way, all that is in the header is simple class with all the public definitions (API) and a factory function for creating an instance of it. All the implementation details are in your source file(s).
Another alternative is similar to the above, but uses a normal class (not a pure virtual one), but still exposes only the public interface. In your source file(s), you do all the work inside a nameless namespace, which can include friend functions from your class definition when necessary, etc. A bit more work, but a reasonable technique.
I bolded those things you might want to lookup and consider when solving your problem.
This is one of the nice features of C#, but unfortunately it is not supported in C++.
Perhaps something like policy based design would do the trick? Multiple Inheritience gives you the possiblity to compose classes in ways you can't in other languages. of course there are gotchas associated with MI so make sure you know what you are doing.
The short answer is yes, it is possible. The correct answer is no, you should never even think about doing it (and you will be flogged by other programmers should you disregard that directive).
You can split the definitions of the member functions into other translation units, but not of the class itself. To do that, you'd need to do preprocessor trickery.
// header file with function declarations
class C {
public:
void f(int foo, int bar);
int g();
};
// this goes into a seperate file
void C::f(int foo, int bar) {
// code ...
}
// this in yet another
void C::g() {
// code ...
}
There must be a reason why you want to split between two headers, so my guess is that you really want 2 classes that are joined together to form components of a single (3rd) class.
I am looking for a nice book, reference material which deals with forward declaration of classes esp. when sources are in multiple directories, eg. class A in dirA is forward declared in class B in dirB ? How is this done ?
Also, any material for template issues, advanced uses and instantation problems, highly appreicated ?
Thanks.
Forward declarations have nothing to do with the directory structure of your project. You can forward declare something even not existing in your project. They are mostly used to resolve cyclic references between classes and to speed up compilation when the complete class declaration is not necessary, and the corresponding #include can be replaced with a forward declaration.
To determine when a forward declaration is sufficient, the sizeof() query can usually answer the question. For example,
class Wheel;
class Car
{
Wheel wheels[4];
};
In this declaration, a forward declaration cannot be used since the compiler cannot determine the size of a Car: it doesn't know how much data the wheels contain. In other words, sizeof(Car) is unknown.
Also regarding templates, forward declared classes cannot be used as template parameters if the template class contains data members of the template parameter (but their pointers can be). For instance,
template<class T> class pointer
{
T *ptr;
};
class Test;
pointer<Test> testpointer;
is legal but
std::vector<Test> testvector will not compile.
Because of the aforementioned limitations, forward declared classes are generally used as pointers or references.
I don't know if there's a book on the subject but you can see this section on c++ faq lite.
Generally speaking you can forward declare in headers as a means of avoiding full includes or as a way to enable circular referencing (bad).
You can use a forward declared type by pointer or reference or return type only.
Large-Scale C++ Software Design by John Lakos (book review here) addresses physical design (files) and logical design and how they relate to software components (which aren't always 1:1 with classes).
if they are in parallel directories you can include it like
#include "../dirB/B.h"
but in header you just call this line for forward decleration
class B;
instead of this, you can seperate your include directories and source directories.
so then you can show include directory as this directory and you can add header by calling
#include "dirB/B.h"
since you will make a forward decleration on header, it wont be problem.