Should this function be static? - c++

I just got a sample of code, which cannot be modified:
#include <iostream>
#include "Image.h"
#include "Ppm.h"
int main() {
Image* ob = 0x0;
try
{
ob = new Ppm("lena.ppm");
long kolor = countColors(*ob);
std::cout << "Unikalnych kolorow: " << kolor << '\n';
}
catch (ImageError& e)
{
std::cout << e.what() << std::endl;
}
delete ob;
return 0;
}
I am confused with line
long kolor = countColors(*ob);
Two questions:
1) should this function be static?
2) should it be in class Image, or in Ppm, which inherit from the first one?

I am confused with line
long kolor = countColors(*ob);
You say that the code cannot be modified, so this line is already there in the code, and I assume the code is compiling/linking OK?
If it compiles OK, the function declaration for countColors() must be getting included from either from Image.h or Ppm.h, or from a header file that one of them includes. It certainly isn't coming from iostream.
If it's linking successfully, the object file or library containing the function definition for countColors() must be getting included in the link step.
We can only guess at the signature of this function; something like:
long countColors(const Ppm& portablePixmap);
...or maybe...
long countColors(const Image& image);
Whatever the signature is, it would not be declared with the keyword static (outside of a class), unless it was only used in the same file it's implemented in.
1) should this function be static?
The short answer is: it's unlikely that it is declared as static (see why below), but that's probably not what you're really asking about.
We know countColors() isn't a class method or instance method, because if it were, you'd have to call it like this1:
long kolor = SomeClass::countColors(*ob); // (class method)
or
long kolor = some_instance.countColors(*ob); // (instance method)
So if it's not a class or instance method, is it static? Probably not; here's why:
Say you've defined a function foo in file foo.c:
void foo(void) { ... }
...you can call it from bar.c:
#include "foo.h" // Tells compiler about foo()
void bar() { foo(); } // COMPILES AND LINKS OK
...but if you had defined the function in foo.c using the static keyword:
static void foo(void) { ... }
...the linker treats it as private to foo.c, so you can't call it from bar.c or any other source file besides foo.c:
#include "foo.h" // Tells compiler about foo()
void bar() { foo(); } // COMPILE OK, BUT LINKER ERROR!
2) should it be in class Image, or in Ppm, which inherit from the first one?
'should' implies that you're looking for the right place to put this method, but you also stated that this code can't be modified.
Are you trying to call this method from your own code, and you're not sure which header file to include, or how to call it?
Sorry, I could give you a better answer if I understood what it was you wanted to do.
1 It's possible to do evil things with macros in C/C++ like #define countColors(x) SomeClass::countColors(x), but we'll ignore that possibility.

Related

How to make a variable available to multiple .cpp files using a class?

This question has derived from this one.
I have a working program which must be split into multiple parts. In this program is needed to use a variable (now it's a GTK+ one :P) many times in parts of the program that will end up in separated .cpp files.
So, I made a simple example to understand how to make variables available to the program parts. A modified version of the previous code would be:
#include <iostream>
using namespace std;
int entero = 10;
void function()
{
cout<<entero<<endl;
//action1...;
}
void separated_function()
{
cout<<entero<<endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
It is needed to split the code correctly, to have function(), another_function() and main() in separated .cpp files,and make entero avaliable to all of them... BUT:
In the previous question #NeilKirk commented:Do not use global variables. Put the required state into a struct or class, and pass it to functions as necessary as a parameter (And I also have found many web pages pointing that is not recommended to use global variables).
And, as far I can understand, in the answer provided by #PaulH., he is describing how to make variables avaliable by making them global.
This answer was very useful, it worked fine not only with char arrays, but also with ints, strings and GTK+ variables (or pointers to variables :P).
But since this method is not recommended, I would thank anyone who could show what would be the correct way to split the code passing the variables as a function parameter or some other method more recommended than the - working - global variables one.
I researched about parameters and classes, but I'm a newbie, and I messed the code up with no good result.
You need to give the parameter as a reference if you want the same comportement as a global variable
#include <iostream>
using namespace std;
// renamed the parameter to avoid confusion ('entero' is valid though)
void function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value
//action1...;
}
void separated_function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value again
//action2...;
}
int main( int argc, char *argv[] )
{
int entero = 10; // initializing the variable
// give the parameter by reference => the functions will be able to modify its value
function(entero);
separated_function(entero);
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
output:
10
11
12
Defining a class or struct in a header file is the way to go, then include the header file in all source files that needs the classes or structures. You can also place function prototypes or preprocessor macros in header files if they are needed by multiple source files, as well as variable declarations (e.g. extern int some_int_var;) and namespace declarations.
You will not get multiple definition errors from defining the classes, because classes is a concept for the compiler to handle, classes themselves are never passed on for the linker where multiple definition errors occurs.
Lets take a simple example, with one header file and two source files.
First the header file, e.g. myheader.h:
#ifndef MYHEADER_H
#define MYHEADER_H
// The above is called include guards (https://en.wikipedia.org/wiki/Include_guard)
// and are used to protect the header file from being included
// by the same source file twice
// Define a namespace
namespace foo
{
// Define a class
class my_class
{
public:
my_class(int val)
: value_(val)
{}
int get_value() const
{
return value_;
}
void set_value(const int val)
{
value_ = val;
}
private:
int value_;
};
// Declare a function prototype
void bar(my_class& v);
}
#endif // MYHEADER_H
The above header file defines a namespace foo and in the namespace a class my_class and a function bar.
(The namespace is strictly not necessary for a simple program like this, but for larger projects it becomes more needed.)
Then the first source file, e.g. main.cpp:
#include <iostream>
#include "myheader.h" // Include our own header file
int main()
{
using namespace foo;
my_class my_object(123); // Create an instance of the class
bar(my_object); // Call the function
std::cout << "In main(), value is " << my_object.get_value() << '\n';
// All done
}
And finally the second source file, e.g. bar.cpp:
#include <iostream>
#include "myheader.h"
void foo::bar(foo::my_class& val)
{
std::cout << "In foo::bar(), value is " << val.get_value() << '\n';
val.set_value(456);
}
Put all three files in the same project, and build. You should now get an executable program that outputs
In foo::bar(), value is 123
In main(), value is 456
I prefer to provide a functional interface to global data.
.h file:
extern int get_entero();
extern void set_entero(int v);
.cpp file:
static int entero = 10;
int get_entero()
{
return entero;
}
void set_entero(int v)
{
entero = v;
}
Then, everywhere else, use those functions.
#include "the_h_file"
void function()
{
cout << get_entero() << endl;
//action1...;
}
void separated_function()
{
cout << get_entero() << endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<< get_entero() <<endl;
//something else with the mentioned variables...;
return 0;
}
If you do not plan to modify the variable, it is generally ok to make it global. However, it is best to declare it with the const keyword to signal the compiler that it should not be modified, like so:
const int ENTERO = 10;
If you are using multiple cpp files, also consider using a header file for your structures and function declarations.
If you are planning on modifying the variable, just pass it around in function parameters.

Is it possible to avoid repeating the class name in the implementation file?

Is there a way to avoid the Graph:: repetition in the implementation file, yet still split the class into header + implementation? Such as in:
Header File:
#ifndef Graph_H
#define Graph_H
class Graph {
public:
Graph(int n);
void printGraph();
void addEdge();
void removeEdge();
};
#endif
Implementation File:
Graph::Graph(int n){}
void Graph::printGraph(){}
void Graph::addEdge(){}
void Graph::removeEdge(){}
I'm guessing this is to avoid lots of "unnecessary typing". Sadly there's no way to get rid of the scope (as many other answers have told you) however what I do personally is get the class defined with all my function prototypes in nice rows, then copy/paste into the implementation file then ctrl-c your ClassName:: on the clip board and run up the line with ctrl-v.
If you want to avoid typing the "Graph::" in front of the printGraph, addEdge etc., then the answer is "no", unfortunately. The "partial class" feature similar to C# is not accessible in C++ and the name of any class (like "Graph") is not a namespace, it's a scope.
No there's not. Not directly at least. You could go for preprocessor tricks, but don't do it.
#define IMPL Graph::
IMPL Graph(int n){}
void IMPL printGraph(){}
void IMPL addEdge(){}
void IMPL removeEdge(){}
Also, you shouldn't even want to do it. What's the point. Besides it being a C++ rule, it lets you know you're actually implementing a member function.
One option is using. If you have method definitions which are in a cpp file that never gets #included, then using is safe (doesn't affect other files):
foo.h:
class FooLongNameSpecialisationsParamaters
{
int x_;
public:
int Get () const;
void Set (int);
};
foo.cpp:
#include "foo.h"
using Foo = FooLongNameSpecialisationsParamaters;
int Foo::Get () const
{
return x_;
}
void Foo::Set (int x)
{
x_ = x;
}
main.cpp:
#include "foo.h"
int main ()
{
//Foo foo; <-- error
FooLongNameSpecialisationsParamaters foo;
return 0;
}
No, there is no way to avoid it. Otherwise, how would you know if a given function definition is for a class function or for a static function?
If you are asking if you can define a member function such as Graph::printGraph without specifying the class name qualification, then the answer is no, not the way that you want. This is not possible in C++:
implementation file:
void printEdge(){};
The above will compile just fine, but it won't do what you want. It won't define the member function by the same name within the Graph class. Rather, it will declare and define a new free function called printEdge.
This is good and proper, if by your point of view a bit of a pain, because you just might want two functions with the same name but in different scopes. Consider:
// Header File
class A
{
void foo();
};
class B
{
void foo();
};
void foo();
// Implementation File
void foo()
{
}
Which scope should the definition apply to? C++ does not restrict you from having different functions with the same names in different scopes, so you have to tell the compiler what function you're defining.
//yes it is possible using preprocessor like this:
#define $ ClassName //in .cpp
void $::Method1()
{
}
//or like this: in the header .h:
#undef $
#define $ ClassName'
// but you have to include the class header in last #include in your .cpp:
#include "truc.h"
#include "bidule.h" ...
#include "classname.h"
void $::Method() { }
//i was using also
#define $$ BaseClass
//with single inheritance than i can do this:
void $::Method()
{
$$::Method(); //call base class method
}
//but with a typedef defined into class like this it's better to do this:
class Derived : Base
{
typedef Base $$;
}
EDIT: I misread your question. This would be an answer to the question whether you can split header-files. It doesn't help you to avoid using LongClassName::-syntaxes, sorry.
The simple answer: You can split up c++-file, but you can not split up header-files.
The reason is quite simple. Whenever your compiler needs to compile a constructor, it needs to know exactly how many memory it needs to allocate for such an object.
For example:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
new Foo() would require the allocation of 12 bytes memory. But if you were allowed to extend your class definitions over multiple files, and hence split header files, you could easily make a mess of this. Your compiler would never know if you already told it everything about the class, or whether you did not. Different places in your code could have different definitions of your class, leading to either segmentation faults or cryptic compiler errors.
For example:
h1.h:
class Foo {
double bar; // 8 bytes
int goo; // 4 bytes
}
h2.h:
#include "h1.h"
class Foo {
double goo; // 8 bytes
} // we extend foo with a double.
foo1.cpp:
#include "foo1.h"
Foo *makeFoo() {
return new Foo();
}
foo2.cpp:
#include "foo2.h"
void cleanupFoo(Foo *foo) {
delete foo;
}
foo1.h:
#include "h1.h"
Foo *makeFoo();
foo2.h:
#include "h1.h"
#include "h2.h"
void cleanupFoo(Foo *foo)
main.cpp:
#include foo1.h
#include foo2.h
void main() {
Foo *foo = makeFoo();
cleanupFoo(foo);
}
Carefully check what happens if you first compile main.cpp to main.o, then foo1.cpp to foo1.o and foo2.cpp to foo2.o, and finally link all of them together. This should compile, but the makeFoo() allocates something else then the cleanupFoo() deallocated.
So there you have it, feel free to split .cpp-files, but don't split up classes over header files.

Global pointer to object causes access violation?

Maybe you will be able to clear something for me, because I don't know exactly where my thinking is flawed. First some code:
Talker.h:
class talker
{
public:
talker();
void sayHello() {cout << "Hello";} ;
};
anotherClass.h:
class anotherClass
{
public:
anotherClass();
void doSomethingYourself() { cout << "will do"; };
void askHimToSayHello() { pointerToTalker->sayHello; };
//Access violation, bad pointer(?)
};
common.h:
static talker *pointerToTalker;
// if I add here "= new talker", code works fine
main.cpp:
#include "common.h"
int main()
{
pointerToTalker = new talker; // Here is the bug, but why?
pointerToTalker -> sayHello; // says Hello alright
anotherClass *pointerToAnotherClass = new anotherClass;
pointerToAnotherClass -> doSomething (); //Does something OK
pointerToAnotherClass -> askHimToSayHello(); // Causes access violation
}
Of course functions are a bit more complex, and each is implemeted in coresponding .cpp including "common.h". My question is - why pointerToTalker, if initialized inside main() does not work inside anotherClass::AskHimToSayHello()? It should pointing to valid memory by the time it is used there.
It is my "Hello world, OOP!" btw, so please be gentle if there is no hope for me :)
Sorry for the childish style btw. It helps me cut down the code I have to something more compact without me loosing the big picture :).
Because
static talker *pointerToTalker;
is not a global. In this context, static gives the variable internal linkage for each translation unit (cpp file + included files) in which common.h is included.
You need to declare it as extern:
extern talker *pointerToTalker;
and initialize it in a single implementation file.
Declaring it static will create a copy of pointerToTalker for each translation unit. So you're initializing the one from main.cpp. Others are left uninitialized, and thus you run into undefined behavior. The proper way is:
//common.h:
extern talker *pointerToTalker;
//common.cpp
#include "common.h"
talker* pointerToTalker = new talker;

From where does the compiler start reading

This is a small program :
#include <iostream>
using namespace std;
int main() {
f();
system("pause");
}
void f() {
static int x = 20 ;
class tester {
public :
tester() {
cout << x ;
}
} x1;
}
The error that i get here is :error C3861: 'f': identifier not found
If i place the function f above main I will get the desired output.
Why it is so ?
I was told that program execution begins at main. According to this the code should run in the first case also.
How does the compiler start reading the program?
The beginning of the compilation and the beginning of the execution of the program are two different things.
The execution starts from the main.
The compilation begins from the beginning of the file; the compiler don't "jump around" the file to find the needed pieces, but it reads the input in a linear fashion (I suspect that this related, among the other things, to the fact that the C++ grammar is really complicated).
When the compiler is at some point in parsing the file, it only knows what has been declared/defined up to that point1.
Because of this, function prototypes (and non-defining declarations in general) have been invented: the prototypes of all the functions defined in the file are put at the beginning of the file, typically after the #include directives or in a separated include file. The prototypes tell to the compiler that such functions will be defined later, and what is the function signature (i.e. name, parameters, return value).
The prototype is made as a normal function, but without the body, which is replaced by a semicolon2. For example, in your code you would write
void f();
before the main.
IIRC there are some relaxations to this rule that allow the compiler to "wait" for some declarations to make some template magic work, but this is not relevant here.
In a prototype is also common not to write the names of the parameters, leaving just their type (this can be done also in function definitions, but it doesn't make much sense there unless you have a formal parameter you don't use). Still, I prefer to leave the parameter names there as a form of documentation.
I was told that program execution begins at main.
And that's exactly the point.
The compiler starts from main, and then sees a call to f(), which it has not encountered so far (as it is defined afterwards), so it does not know what to do with it.
If you want to define f after main you can place a function prototype before, such as
#include <iostream>
using namespace std;
void f(); // <--- This tells the compiler that a function name f will be defined
int main() {
f();
system("pause");
}
void f() {
static int x = 20 ;
class tester {
public :
tester() {
cout << x ;
}
} x1;
}
To be able to call a function it must have been declared at some earlier point in the code. This is just a rule of the language designed to help compilers.
You can declare the function earlier with e.g.
void f();
...and then define it after main as you have done.
The compiler starts at the top and reads down to the bottom.
you'll need to have something like:
#include <iostream>
using namespace std;
void f();
int main() {
f();
system("pause");
}
void f() {
static int x = 20 ;
class tester {
public :
tester() {
cout << x ;
}
} x1;
}
No, the compiler needs to see at least a declaration of f() before it is used. A c(++) code file is a simple text file and must be read from begin to end by the compiler.
During the compilation process, when the compiler is evaluating main() it needs to know what f() is in advance to be able to generate the correct assembly code to call this function. That's why you need to put it before main() in this case.
As an alternative you can declare the prototype of f() before main() so the compiler knows it's a local function declared somewhere else on your file:
void f(); // prototype
int main()
{
// .. code ..
}
void f() // implementation of f()
{
// .. code ..
}

What if the default parameter value is defined in code not visible at the call site?

I've found some strange code...
//in file ClassA.h:
class ClassA {
public:
void Enable( bool enable );
};
//in file ClassA.cpp
#include <ClassA.h>
void ClassA::Enable( bool enable = true )
{
//implementation is irrelevant
}
//in Consumer.cpp
#include <ClassA.h>
....
ClassA classA;
classA.Enable( true );
Obviously since Consumer.cpp only included ClassA.h and not ClassA.cpp the compiler will not be able to see that the parameter has a default value.
When would the declared default value of ClassA::Enable in the signature of the method implementation have any effect? Would this only happen when the method is called from within files that include the ClassA.cpp?
Default values are just a compile time thing. There's no such thing as default value in compiled code (no metadata or things like that). It's basically a compiler replacement for "if you don't write anything, I'll specify that for you." So, if the compiler can't see the default value, it assumes there's not one.
Demo:
// test.h
class Test { public: int testing(int input); };
// main.cpp
#include <iostream>
// removing the default value here will cause an error in the call in `main`:
class Test { public: int testing(int input = 42); };
int f();
int main() {
Test t;
std::cout << t.testing() // 42
<< " " << f() // 1000
<< std::endl;
return 0;
}
// test.cpp
#include "test.h"
int Test::testing(int input = 1000) { return input; }
int f() { Test t; return t.testing(); }
Test:
g++ main.cpp test.cpp
./a.out
Let me admit first that this is the first time I have seen this type of code. Putting a default value in header file IS the normal practice but this isn't.
My guess is that this default value can only be used from code written in the same file and this way the programmer who wrote this wanted to put it in some type of easiness in calling the function but he didn't want to disturb the interface (the header file) visible to the outside world.
Would this only happen when the method
is called from within files that
include the ClassA.cpp?
That's correct. But note that doing so will almost certainly produce multiple definition errors, so the default is only really available from its point of definition within ClassA.cpp.
Put the default value in the declaration, not the definition.
class ClassA {
public:
void Enable( bool enable = true );
};