An issue with a non-member function - c++

A problem I'm working on is asking me to define an istream constructor inside the class body. Let's call the class Sound. Now this constructor uses a function in its own body. But the function is supposed to be a non-member function. I have it defined in another file, but I have it declared in the header that contains the class definition itself. I've placed the header in the other file containing the non-member functions already.
The problem is, one of the parameters of the non member function has type Sound and it performs operations on the type Sound objects.
When I declare this function in the header file, if I put it before the class definition I get an error saying the objects haven't been defined.
When I put the declaration after the definition, the constructor now tells me that the function inside it's body is undefined.
If I put the declaration inside the class body, it becomes a member function.
The problem didn't explicitly state that I cannot make the function a member function so I am wondering if there is a way to overcome this catch-22.

You do not necessarily need to make the function member. You can have at least two ways to solve it in a different manner.
The problem is that you are having all this in a situation where a Sound object is not yet defined if I understand correctly.
1) You can refactor your code a bit as demonstrated below.
header file:
class Sound
{
public:
Sound();
doStuff();
}
cpp file:
void non_member_function(Sound sound)
Sound::Sound() { non_member_function(*this); }
Sound::doStuff() {}
void non_member_function(Sound sound) { sound.doStuff(); }
2) if you insist on the scenario aforementioned, you put a Sound sound forward declaration before the non-member function to get the type recognized. Or, you can just put the declaration after the class declaration.
header file:
class Sound
{
public:
Sound();
doStuff();
}
void non_member_function(Sound sound)
cpp file:
Sound::Sound() { non_member_function(*this); }
Sound::doStuff() {}
void non_member_function(Sound sound) { sound.doStuff(); }

Looks like best thing to do is to use forward declaration for class, before the function:
header:
class Sound;
void f(Sound s);
class Sound
{...};

In c++ you can define a function as a member function or a non-member function. If it is not specified or required that the function be define as member or non-member as you have pointed out, then I would opt for an easy or simple solution.
Calling a non-member function within a constructor might require you, to use a certain technic to go about this function call, now that might not be required if the function was defined as a member function.

Related

In C++, how to write full implementation in header for classes and functions (possibly templated)

I usually declare in header file and implement in cpp file, but now I am doing an assignment, and, apparently for brevity, the instructor doesn't want me to do that, but insists that I write all the code in header files.
So, what is the best way to do that?
For classes, should I declare everything first, and then go to the bottom of the page and start implementing?
class myClass
{
void myMethod();
}
void myClass::myMethod() { //.... }
or should I just implement as I declare
class myClass
{
void myMethod() { //... } ;
}
What about free functions?
And when should I write "inline"?
or should I just implement as I declare
Yes, implement them in class, not out of class. When the (questionable) reasoning of your instructor for putting everything into a header refers to brevity, this is obviously the way to go.
What about free functions?
Same as with member functions, define them on the go.
And when should I write "inline"?
You should add inline to all ordinary free functions. It's unnecessary for function templates or in-class member function definitions. When you can use C++17, consider inline variables, too.

How to limit a function scope in the same file as it is defined in c++?

I have public member functions which are calling private member function. I want to limit the scope of the private member function within the file where definition of private member function is available. In C, I used static before the function name to limit its scope within the file, how do I achieve it in C++.
class Base
{
public:
void XYZ1(void);
void XYZ2(void);
private:
void fun(void);
};
void Base::XYZ1(void)
{
fun();
}
void Base::fun(void)
{
// do something;
}
Now if the member function XYZ2 is defined in some other .cpp file , it should not be allowed to call fun() from it. Basically restrict the fun() function to file scope.
In a1.cpp
void Base::XYZ2(void)
{
fun();// this should result in some error saying fun() is not defined in its scope.
}
I want to limit the scope of the private member function within the file where definition of private member function is available.
A private member function cannot be used by another class or function unless they are granted friend-ship by the class. In that sense, the scope in which the function can be called is already limited.
Having said that, any member function of the class or any class or function that has been granted friend-ship by the class will be able to call the private member function.
The only way to prevent that function from being called outside the file in which it is defined is to make it a non-member static function in the .cpp file. or put it in an anonymous namespace in the .cpp file.
Now if the member function XYZ2 is defined in some other .cpp file ,
it should not be allowed to call fun() from it. Basically restrict the
fun() function to file scope. In a1.cpp
You can put the function in an anonymous namespace (in the cpp file where used). The linkage will become internal, and the name won't be available for access from any other file. One can get the same effect when making the function static (in the cpp file).
If you need to access internal/private members, you could use a nested class who's implementation is defined in the associated cpp file:
//h
class Nesting
{
//...
private:
struct MyPrivateFunctions;
};
//cpp
struct Nesting::MyPrivateFunctions
{
static void f1(Nesting& this);
static void f2(Nesting& this);
//etc...
};
I've passed Nesting as parameter that MyPrivateFunctions may access its private members (since it is nested, this is permitted).
Note that this is very similar to the Impl trick mentioned elsewhere, but it also allows independent member function definitions in other units, and it does not need instantiation.
Most people are suggesting you to use anonymous namespace in C++. But, this would only be feasible if you wanted to do something like, declaring a global variable/function which is supposed to be used strictly inside the file under which it is defined.
We cannot use namespace within the class as per C++ standards, for which you may want to take a look at this discussion: Why can't we declare a namespace within a class?
I used static before the function name to limit its scope within the file.
This worked for you but the understanding here is wrong as static was never intended to be used as scope specifier, its a storage specifier and its lifetime is throughout the program life. You can still access the static variable from other files in several ways, however the compiler here does not provide an externally visible linker symbol and thus cannot be accessed by other translation units / files.
As per the public member functions are concerned they should be allowed to use this private function from whichever file it is defined in. So that the relation between the class member functions are not destroyed. I suppose you would now stop treating static as scope specifier :)
Or you can use the good old Impl- trick if you do not want to show the "hidden" functions of a class to the outside. Private functions are still listed in the header file, after all.
// Foo.h
class FooImpl; // forward declearation
class Foo
{
FooImpl *m_pImpl;
public:
Foo(); // Default constructor (and any other) create instance of FooImpl.
~Foo();
};
// Foo.cpp
class FooImpl
{
// members of hidden types, secrets, methods, ... anything you do not want to show to users of class Foo.
};
Foo::Foo() : m_pImpl(new FooImpl()) {}
Foo::~Foo()
{
delete m_pImpl; m_pImpl = nullptr;
}
As can be seen, with the impl trick you cannot only hide functions, but also data members of a class and type dependencies which would be incurred if the members were part of Foo class.
A way to solve this problem is by using a so called 'facade'. Basically, you have two classes: The first class has the private method which you want to hide, where as the second class implements a wrapper which just provides the methods you want to be accessible. The second class wraps an instance of the first. That's how the whole trick works.
https://en.wikipedia.org/wiki/Facade_pattern

How do these two functions defined in the same class manage to call each other without forward declaration?

For the time I'm learning to code with boost/asio. Many code samples make use of the combination of async_accept and bind. In the server code , i come across some thing like this:
class Tcp_server
{
public:
Tcp_server()
{
}
void start_accept(int a)
{
if(a>0)
{
cout<<a<<endl;
handle_accept(a-1);
}
}
void handle_accept(int a)
{
if(a>0)
{
cout<<a<<endl;
start_accept(a-1);
}
}
};
If i make an instance of Tcp_server and call either handle_accept or start accept, it works. But if I drop the Tcp_server class encapsulation, the compiler would complain "handle_accept is not declared". I'm just wondering if the compiler automatically forward declare all the functions defined in the same class. Can anyone explain why?
Functions defined in the definition of a class have exactly the same semantics as if they are only declared in the class definition and then defined immediately after the class definition. The only difference is that such member functions are implicitly declared inline while a function definition is either not-inline or explicitly inline. That is, from the compiler's point of view the functions are declared and the class is defined before the function definitions are considered.
The reason for defining the function after the class definition is simple: without doing so, the class would be incomplete and look-ups of members would fail which is clearly not desirable for member function definitions. As a side effect, functions can readily refer to each other. Since defining member functions in the class definition is primarily for convenience it would also be somewhat inconvenient to require declaration for member functions used later.

Resolving Inclusion Ordering

I am working on a codebase that is not my own, that has the following layout:
object.h:
// Objects are defined
// #include "tickets.h" (functions to access the objects)
// An access-handler object is defined
I want to introduce a class that knows about the objects, can be accessed from functions in tickets.h, but can also use the access-handler object. The functions are separate, i.e. class functions that are called in tickets.h do not use the access-handler (I wouldn't know where to start if that weren't the case).
Therefore my class needs to be defined before tickets.h, but some of its functions need to be defined after the access-handler. Is there a way to do this without splitting it up into two header files something like the following:
// Objects are defined
// -- include declaration of class, and definition of functions that tickets.h needs
// #include "tickets.h"
// An access-handler object is defined
// -- include functions of class that need the access-handler
This seems very messy splitting things up like this into two separate files, I was hoping to keep everything contained.
Thanks for any help, I clearly only have a very rudimentary understanding of declarations/definitions in c++.
EDIT: If I use forward declaration and include it before tickets.h (with the class declared in mynewclass.h and functions defined in mynewclass.cc) will mynewclass.cc be able to use objects declared after the inclusion of mynewclass.h? Namely the access-handler object.
EDIT2: Something like this:
object.h:
class obj { // definition }
#include "tickets.h"
class obj_handler {
public void handle { // code }
}
tickets.h:
void do_something(obj o){
communicator.foo();
}
My object (communicator):
class communicator {
public:
void foo() { // code }
void bar() { // use handle() from obj_handler }
}
As you can see, my communicator needs to be used in tickets.h, but can't be defined until after obj_handler. So where should I include it?
If I correctly understand your question - you can use forward declaration to solve this problem. This will allow you to declare some class before defining it's methods. For example:
// this is forward declaration of class A, no definition provided
class A;
class B
{
// uses A
A * a_;
};
// class A definition
class A
{
// may use class B now
B * b_;
};
I'm not quite sure whether I understand this right and don't have enough reputation here yet to make this a comment, so let me try to answer your question this way, please feel free to follow up if I'm guessing wrong:
I believe what you are referring to is an entire class definition, i.e., one including all function definitions within the class declaration. Other than that, it is not very common to see object definitions followed by preprocessor directives. What is typical though is a forward declaration of functions and a class prototype.
So, for example, you could declare in some header.h:
class C
{
public:
void method1(void);
int method2(void);
};
And in some implementation.cpp the definition of the functions like:
void C::method1(void) { /*...*/ }
In the other file preceded in the inclusion chain by your access-handler you then define the other function:
int C::method2(void) { /*...*/ }
What do you mean by access-handler, by the way?
Oh, and your linker likely will yell somewhat at you if you do function definition in a header file.
With regard to your addenda: everywhere you put a forward declaration, loosely speaking, the compiler will insert a copy of the declaration in question, consider it a soft link in the context of file systems. There are negative implications associated with it, like increased duration and the memory load of compilation if you have many forward declarations of the function signature or class. It's impossible to tell whether this will word in your particular situation since only you know the actual code in question. But most likely it would work.
Take a look at these pages:
http://en.wikipedia.org/wiki/Forward_declaration
When can I use a forward declaration?

How come these functions are called before being defined?

this is the cpp of a Time function. The code is defining functions of a time.h file on this time.cpp. My question is: How come this function definition is possible if the functions inside this fct are defined afterwards? Thank you
void Time::setTime(int hour, int minute, int second)
{
sethour(hour);
setminute(minute);
setseconds(seconds);
}
void Time::sethour( int h)
{ ....
You don't need a definition to call a function, you only need a declaration. The compiler is happy with the declaration alone. The linker requires code to be generated, and it requires the definition, but it doesn't matter when you define them, as long as you do.
In your case, the declaration of every member function is visible to all other member function, even if inside the class definition it came afterwards:
class Time
{
void setTime(); //setTime knows about sethour even if it's before
void sethour();
};
Outside of a class, this doesn't hold, meaning you need a declaration before using a method. The declaration is just the prototype:
void foo();
void goo()
{
foo(); //can call foo here even if it's just declared and not defined
}
Presumably because they were declared somewhere above (e.g. in the header file), and that's what's important.
It's best to imagine that the compiler operates in a "one-pass" approach; it processes your code linearly from top-to-bottom. Therefore, it needs to know that functions exist (i.e. their name, arguments and return type) before they are used, in order to establish that the caller is not doing something invalid. But the actual function definition (i.e. its body) is not relevant for this task.
You can choose when to define them.