I found this function in the header file of an abstract class:
virtual ostream & print( ostream & out ) const;
Can anyone tell me what kind of function this is and how to declare it in a derived class?
From what I can tell, it looks like it returns a reference to an outstream.
If I implement it in my cc file with nothing in it, I get a compiler error:
error: expected constructor, destructor, or type conversion before ‘&’ token
Can someone show me a simple implementation of how to use it?
You probably forgot to include iostream which makes ostream visible. You also need to change this into std::ostream, because C++ standard library names are within the namespace std.
Do not write using namespace std; in a header-file, ever!
It's ok to place it into the implementation file, if you want, or if you write up an example for a friend. Because any file that includes that header will have all of the standard library visible as global names, which is a huge mess and smells a lot. It suddenly increases the chance for name-clashes with other global names or other using'ed names - i would avoid using directives at all (see Using me by Herb Sutter). So change the code into this one
#include <iostream>
// let ScaryDream be the interface
class HereBeDragons : public ScaryDream {
...
// mentioning virtual in the derived class again is not
// strictly necessary, but is a good thing to do (documentary)
virtual std::ostream & print( std::ostream & out ) const;
...
};
And in the implementation file (".cpp")
#include "HereBeDragons.h"
// if you want, you could add "using namespace std;" here
std::ostream & HereBeDragons::print( std::ostream & out ) const {
return out << "flying animals" << std::endl;
}
some implementation:
ostream& ClassA::print( ostream& out) const
{
out << myMember1 << myMember2;
return out;
}
Returning the same ostream allows combinations like
a.print( myStream) << someOtherVariables;
However, it is still strange to use it this way.
Regarding the error, ostream is part of std namespace, and not part of the global namespace or the namespace the class you're refering is part of.
#include <iostream>
using namespace std;
struct A {
virtual ostream & print( ostream & out ) const {
return out << "A";
}
};
It is common to make a print function virtual, because the << operator commonly used for stream output cannot be made so (because it is not a member function).
Related
See code below
#include <iostream>
#include <string>
namespace stringhelper
{
std::string to_string(int n) { return "0"; } // ignore wrong implementation. simplified for example purpose
}
using stringhelper::to_string;
class TestClass
{
public:
std::string to_string() const { return "TestClass:" + to_string(m_value); }
private:
int m_value;
};
int main()
{
TestClass tc;
std::cout << tc.to_string();
}
If TestClass does not implement function to_string(), within TestClass, it is able to resolve to_string(m_value) to stringhelper::to_string(int). However, the moment TestClass implements function to_string(), the compiler is unable to resolve to_string(int) to stringhelper::to_string.
Rather, it insists/resolves the function to TestClass::to_string and gave an error that the function TestClass::to_string does not take in 1 arguments.
Why is this so?
Environment:
Visual Studio 2008 Professional Edition 9.0.21022.8 RTM
Configuration: Win32
Windows 8
This behavior is not limited to Visual Studio 2008. If tested in modern Clang implementations you will see the same behaviour. As you may know, functions in derived classes which don't override functions in base classes but which have the same name will hide other functions of the same name in the base class.
The "problem" here is that you, by using the using statement introduces a function named to_string into a scope that is essentially a victim of the exact same thing as what happens in the above example, when looking at it from inside your class.
If the standard had you call member functions with this->foo() this would probably not have been an issue. But since function calls within a class are presumed to be part of the class and only if not found looked for in other scopes this becomes an issue.
Since you have an implementation in your class, that has priority and will be used. Since you want a version that takes an int as an argument, an overloaded version of your member function will be looked for and since it does not exist you get the error you see.
This is part of why using namespace can often introduce errors that might be unintuitive to understand. If you want to make sure you use the stringhelper::to_string implementation while you are in a class with a function that has the same name you have to be explicit.
This would work fine for instance, even if you keep your using statement.
#include <iostream>
#include <string>
namespace stringhelper
{
std::string to_string(int n) { return "0"; } // ignore wrong implementation. simplified for example purpose
}
using stringhelper::to_string;
class TestClass
{
public:
std::string to_string() const { return "TestClass:" + stringhelper::to_string(m_value); }
private:
int m_value;
};
int main()
{
TestClass tc;
std::cout << tc.to_string();
}
Simple question - why do I have to #include "listType.cpp" or get linker errors here? Why can't I just include the header?
stockListType.h:
#ifndef stockListType_H
#define stockListType_H
#include "listType.h"
#include "stockType.h"
#include "listType.cpp"
using namespace std;
class stockListType : public listType<stockType>
{
private:
unique_ptr<int[]> sortIndicesByGainLoss;
public:
void sortByStockSymbol();
void sortByGainLoss();
stockListType(int maxSize);
};
#endif
This happens because in a traditional C++ compiler approach template code "doesn't exist" as a "material execution entity" until it's instantiated for some "real" types (stockType in your case). There're however techniques called explicit instantiation which allows to to specify during processing of "listType.cpp" that later you will need an instance of the code for e.g. stockType, otherType and int. Read from this: http://msdn.microsoft.com/en-us/library/by56e477.aspx or this: http://www.cplusplus.com/forum/articles/14272/ or this: How do I explicitly instantiate a template function?
Also another reason for using a source, not pre-compiled code of template classes and functions is that it's possible to override later an implementation of a given template class, method or function for a particular template argument (recall the famous std::cout << "Hello, World " << 1 << MyClassObject << std::endl, that's the classical case when operator<<(ostream&, T&) is defined for each particular type separately.
Besides, if you take a look into standard C++ STL library (e.g. <vector> or <string>) you will see that the whole code of the classes is right in header files, or files included from header files (.tcc) even a rather complex one (see Boost.Spirit, well, if you're brave enough :) ). That's because it's not possible to create an executable code for vector until vector elements (stockType etc) are defined.
I have a cyclical redundancy circular dependency between two classes in my project, StatusEffect and BaseCharacter.
Both classes need to be aware of each other as the BaseCharacter needs to store a set of StatusEffects and StatusEffect needs to be able to do operations on BaseCharacter. I don't think it's possible to eliminate this behavior and still have it work correctly. Here's what I'm trying to do right now:
Base Character exists inside the namespace Game::Character and StatusEffect exists inside the namespace Game::StatusEffects
inside StatusEffects.h, I forward declared BaseCharacter like so:
namespace Game {
namespace Character {
class BaseCharacter;
}
}
then below it I have:
namespace Game
{
namespace StatusEffects
{
class StatusEffect
{
public:
virtual void TickCharacter(Game::Character::BaseCharacter* character, int ticks = 1)
{
std::cout << "Name " << character->GetName() << std::endl;
}
protected:
private:
std::string name;
int StatusEffectUID;
};
}
}
However, this is giving me a compiler error:
Error 1 error C2027: use of undefined type 'Game::Character::BaseCharacter'
I thought that because I'm using a pointer, this forward declaration is fine. Is there something else I need to forward declare? I dont need to forward declare the whole class definition do I?
You can't call a method through a pointer to a forward-declared class. You have to move this code somewhere where the class is already defined - for example into a .cpp file that includes both classes definition.
Your forward declaration is fine. However, you must not refer to any of the members of such a class.
You should only declare the TickCharacter method in the header. You should then define the StatusEffect::TickCharacter method in its own module file after #include ing the header file which contains the full declaration of BaseCharacter.
Do I have to put code from .cpp in a namespace from corresponding .h or it's enough to just write using declaration?
//file .h
namespace a
{
/*interface*/
class my
{
};
}
//file .cpp
using a::my; // Can I just write in this file this declaration and
// after that start to write implementation, or
// should I write:
namespace a //everything in a namespace now
{
//Implementation goes here
}
Thanks.
I consider more appropriate to surround all the code that is meant to be in the namespace within a namespace a { ... } block, as that is semantically what you are doing: you are defining elements within the a namespace. But if you are only defining members then both things will work.
When the compiler finds void my::foo(), it will try to determine what my is, and it will find the using a::my, resolve my from that and understand that you are defining the a::my::foo method.
On the other hand this approach will fail if you are using free functions:
// header
namespace a {
class my { // ...
};
std::ostream & operator<<( std::ostream& o, my const & m );
}
// cpp
using a::my;
using std;
ostream & operator<<( ostream & o, my const & m ) {
//....
}
The compiler will happily translate the above code into a program, but what it is actually doing is declaring std::ostream& a::operator<<( std::ostream&, a::my const & ) in the header file --without implementation--, and defining std::ostream& ::operator<<( std::ostream &, a::my const & ) in the cpp file, which is a different function. Using Koening lookup, whenever the compiler sees cout << obj with obj of type a::my, the compiler will look in the enclosing namespaces of cout and my (std, and a) and will find that there is an a::operator<< declared but never defined in namespace a. It will compile but not link your code.
If I understood the question correctly, you can have just using a::my and then just implement the methods, like
using a::my;
void my::doSomething() {}
You can do it. But, should you?
It's an uncommon practice, and it will probably lead to a proliferation of using a::Type; for every type from namespace 'a' used in the .cc file. Whether that is a good thing is for you to decide, but I'd vote against it :)
I'm working in Visual Studio 2008 on a C++ programming assignment. We were supplied with files that define the following namespace hierarchy (the names are just for the sake of this post, I know "namespace XYZ-NAMESPACE" is redundant):
(MAIN-NAMESPACE){
a bunch of functions/classes I need to implement...
(EXCEPTIONS-NAMESPACE){
a bunch of exceptions
}
(POINTER-COLLECTIONS-NAMESPACE){
Set and LinkedList classes, plus iterators
}
}
The MAIN-NAMESPACE contents are split between a bunch of files, and for some reason which I don't understand the operator<< for both Set and LinkedList is entirely outside of the MAIN-NAMESPACE (but within Set and LinkedList's header file).
Here's the Set version:
template<typename T>
std::ostream& operator<<(std::ostream& os,
const MAIN-NAMESPACE::POINTER-COLLECTIONS-NAMESPACE::Set<T>& set)
Now here's the problem: I have the following data structure:
Set A
Set B
Set C
double num
It's defined to be in a class within MAIN-NAMESPACE. When I create an instance of the class, and try to print one of the sets, it tells me that:
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'const MAIN-NAMESPACE::POINTER-COLLECTIONS-NAMESPACE::Set' (or there is no acceptable conversion)
However, if I just write a main() function, and create Set A, fill it up, and use the operator- it works.
Any idea what is the problem? (note: I tried any combination of using and include I could think of).
Strange - even though putting free functions associated with a type to a different namespace is a bad practice, the global namespace declarations are always visible.
The only thing I can think of is that declaration with the same name in MAIN-NAMESPACE would shadow the one in the global namespace - isn't there an operator<<, possibly for totally unrelated type, in MAIN-NAMESPACE? If so, you should fix that by using ::operator<< declaration in MAIN-NAMESPACE. Example:
namespace A
{
namespace B
{
class C{};
}
}
void f(A::B::C*);
namespace A
{
void f(int*); // try commenting
using ::f; // these two lines
void g()
{
B::C* c;
f(c);
}
}
OK I figured this out.
jpalecek's intuition about there existing another operator<< in the namespace was correct (apparently I forgot to comment it out).
The lookup rules for namespaces first start the search in the function call's namespace and search up the enclosing namespaces, right up to the global namespace (then it does the Argument dependent lookup if no match is found). However, if along the way it finds some match for operator<<, it stops the search, regardless of the fact that the types used in those functions may be incompatible, as was the case here.
The solution is either to include it into the MAIN-NAMESPACE (which I'm not allowed to), or import it from the global namespace with "using ::operator<<".
Try calling the function explicitly?
::operator<<( cout, myObj );
As SoaBox pointed out, try calling it explicitly.
For your information, if you wish to call a global function which has been hidden in the current namespace precede the function with :: to bypass the local function and call the global function.
Try calling the function explicitly?
::operator<<( cout, myObj );
Yes, that does work!
it will try to find the f function in
the current namespace (at the place of
call) or in the enclosing namespaces
of c1 and c2 types (namespace1,
namespace2::namespace3), but it will
not try other namespaces in the
search.
So let's see if I got this right: the reason invoking the operator<< from a main() function worked is because I was in the global namespace (as was operator<<).
The reason it failed when invoking from the class I implemented is because the class was in a not global namespace and there were no variables in it that pointed the compiler towards the global namespace.
OK people asked for a specific examples, so here's the relevant part of the code.
//Disclamer: in the slim case someone from my uni sees this, encounters it in the submission file, and decides I copied it or something, my student number is 311670137
This is the header file Set.h:
namespace MTM {//This is the MAIN-NAMESPACE
namespace PointerCollections {
(ITERATORS AND PREDICATE CLASSES)
template<typename T>
class Set {
public:
/////////////////////////////////
// Definitions
/////////////////////////////////
private:
/////////////////////////////////
// Definitions
/////////////////////////////////
};
///////////////////////////////////////////////////////////////////////////////
// The implementation part.
///////////////////////////////////////////////////////////////////////////////
}
}
// operator<< - the same a Set::print(std::ostream& os,
// const BinaryPredicate<T>& predicate)
// function called with the 'predicate' parameter omitted
template<typename T>
std::ostream& operator<<(std::ostream& os,
const MTM::PointerCollections::Set<T>& set){
set.print(os);
return os;
}
This is what I defined in a different file:
namespace MTM {
using std::ostream;
class Schedule {
public:
///////////////////
//Definitions, including:
///////////////////
void registerStation(string stationName);
void reportRegisteredStations(std::ostream& outputStream) const;
private: //My database
//All the classes Set recieves are defined elsewhere
Set<RegisteredStation> places;
Set<BusLine> busses;
Set<TrainLine> trains;
double tarifForBuses;
double tarifForTrains;
};
}
And here's from the main:
Schedule s();
s.registerStation("1");
s.reportRegisteredStations(cout);//This invokes the error. Definition follows:
reportRegisteredStations is defined as:
void Schedule::reportRegisteredStations(std::ostream& outputStream) const{
outputStream<<places;
}
This works for me
#include <iostream>
#include <string>
using std::string;
namespace MTM {//This is the MAIN-NAMESPACE
namespace PointerCollections {
template<typename T>
class Set {
};
}
}
template<typename T>
std::ostream& operator<<(std::ostream& os,
const MTM::PointerCollections::Set<T>& set){
return os;
}
namespace MTM {
using std::ostream;
using PointerCollections::Set;
class Schedule {
public:
///////////////////
//Definitions, including:
///////////////////
void registerStation(string stationName);
void reportRegisteredStations(std::ostream& outputStream) const;
private: //My database
//All the classes Set recieves are defined elsewhere
Set<int> places;
Set<int> busses;
Set<int> trains;
double tarifForBuses;
double tarifForTrains;
};
void Schedule::reportRegisteredStations(std::ostream& outputStream) const{
outputStream<<places;
}
}
int main()
{
MTM::Schedule s;
s.reportRegisteredStations(std::cout);
}
CORRECTION: The text below is based on experience with the g++ family of compilers. After the comment to the answer I have reread the standard (which states that ADL will be used over regular name lookup, and regular name lookup should find the operator<<). I have also tried with comeau compiler (the most standard compliant compiler I know of) and the symbol is found. It seems as a problem with g++ (tried versions 3.3, 4.1, 4.3).
Original answer:
Search for Koening lookup (technically ADL: Argument dependent lookup).
The short answer is that if you have the following class:
namespace test {
class A {};
}
the stream insertion operator should be defined as:
namespace test {
std::ostream& operator<<( std::ostream&, A const & );
}
Functions or operators should be defined in the same namespace as one of the arguments that it takes. (*)
When the compiler finds a function call such as:
namespace test2 {
void g() {
namespace1::class1 c1;
namespace2::namespace3::class2 c2;
f( c1, c2 );
}
}
it will try to find the f function in the current namespace (at the place of call) or in the enclosing namespaces of c1 and c2 types (namespace1, namespace2::namespace3), but it will not try other namespaces in the search.
(*) In this case, you are pretty much limited to the test namespace, as you are not allowed to add a function to the std namespace (only template specializations).
End of original post.
Even if as commented before this may just be a problem with the compiler, it is common usage and recommended to define all free functions that operate on a user defined type in the same namespace as the type itself.