I've done this so many times, yet the reason why Visual Studio is complaining about this escapes me.
Manipulator.cpp:
#include "Manipulator.h"
Manipulator::Manipulator() {}
Manipulator::~Manipulator() {}
void proc(std::string p, int f, std::string c)
{
// switch-case p to c based on f:
return;
}
Manipulator.h: (void -proc- has a curly underscore, and that's what's driving me up the wall.)
#ifndef MANIPULATOR_H
#define MANIPULATOR_H
#include <string>
class Manipulator
{
private:
protected:
public:
Manipulator() ;
~Manipulator() ;
void proc(std::string, int, std::string);
// function definition for 'proc' not found.
};
#endif MANIPULATOR_H
main.cpp
#include "Manipulator.h"
...
int main()
{
...
Manipulator m;
...
m.proc(opdBMP, fxn, newBMP);
return 0;
}
What is it that VS wants so that I can get a move on? It is telling me that there are two linker errors: LNK2019 and LNK1120 (unresolved external). (I used to keep track of these kinds of errors but lost the file as a log with these.)
The compiler is correct in complaining, because the definition should be
void Manipulator::proc(std::string p, int f, std::string c) {
...
}
You just defined a free function instead of a member of Manipulator.
Related
I am experiencing a strange issue where attempting to inline the accessors for my "Person" class causes the code to fail to compile.
The following code will compile and run successfully (Using Visual Studio 2012):
Person.h
#pragma once
#include <string>
using namespace std;
class Person
{
public:
Person(string name, int age = 0);
~Person(void);
// Accessors
string name(void) const;
int age (void) const;
private:
string m_name;
int m_age;
};
Person.cpp
#include "stdafx.h"
#include "Person.h"
Person::Person(string name, int age) :
m_name(name),
m_age (age )
{}
Person::~Person(void) {}
string Person::name(void) const
{
return m_name;
}
int Person::age(void) const
{
return m_age;
}
header_test.cpp
#include "stdafx.h"
#include <iostream>
#include "Person.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Person p("Joe");
cout << p.name() << endl;
return 0;
}
If I change my accessors to be defined as inline functions the code breaks.
Inlining the accessors in Person.h
// Accessors
inline string name(void) const;
inline int age (void) const;
Inlining the accessors in Person.cpp
inline string Person::name(void) const
{
return m_name;
}
inline int Person::age(void) const
{
return m_age;
}
Doing this produces the following errors:
1>header_test.obj : error LNK2019: unresolved external symbol "public: class std::basic_string,class std::allocator > __thiscall Person::name(void)const " (?name#Person##QBE?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) referenced in function _wmain
1>fatal error LNK1120: 1 unresolved externals
God that error message is cryptic... Thank you for all of that oh so useful information Microsoft/Visual Studio!
I know the inline keyword is just a "hint" to the compiler and probably has no real value here, but it still shouldn't break the code!
Why is this happening?
I am not a language lawyer, so I can't tell if the compiler behaviour is legitimate or not. Yet, I can explain what is happening.
When you are marking your functions inline, you are not hinting the compiler that it can inline this function. Since over 10 years compilers do not need your hint here. They know when to inline. Instead, what you do, you indicate the function definition to be local for every translation unit it is included in. For this definition should be available.
Effectively what you said is that name() definition should be local for every .cpp file, but you didn't make it available for every .cpp file! I still believe the compiler could give a warning here.
You need to define the function body in the header if you want to use the inline keyword. inline also does more than just give a hint to the compiler: it more or less shuts down the "one definition" rule* about functions being defined once and only once.
Furthermore, if you define class member functions inside the headers, ala
class Foo {
int bar() { return 5; }
};
they get "inlined" by default, so there's no reason to type the keyword out :-)
* Technically not, but for simplicity you can think of it as behaving that way. See the comment below by SergeyA.
I'm having difficulty interpreting some of my results, which I would expect to behave the same but are not.
I am trying to write a method that returns a function pointer getPtrFn
I have a main.c file reading
#include <iostream>
#include "test.hpp"
int main(int argc, char* argv[]){
Test test;
void (*fPtr)(void) = test.getPtrFn();
return 0;
}
A test.hpp file that reads
#ifndef _test_h
#define _test_h
class Test {
private:
void (*ptrFn)(void);
public:
Test(){};
void (*getPtrFn(void))(void){
return ptrFn;
};
~Test();
};
#endif
And a test.cpp file that reads
#include "test.hpp"
Test::~Test(){}
This runs fine. However, when I move the implementation for *getPtrFn(void) to the implementation file (revised files shown below),
test.hpp:
#ifndef _test_h
#define _test_h
class Test {
private:
void (*ptrFn)(void);
public:
Test(){};
void (*getPtrFn(void))(void);
~Test();
};
#endif
test.cpp:
#include "test.hpp"
void (Test::*getPtrFn)(void){
return ptrFn;
};
Test::~Test(){}
I get the compile error
test.cpp:16:9: error: use of undeclared identifier 'ptrFn'
My understanding of the language syntax is that they would be treated the same. So what gives?
-Jeff
You need
void(*Test::getPtrFn(void))(void)
{
return ptrFn;
}
instead of void (Test::*getPtrFn)(void){...}. void (Test::*getPtrFn)(void) is the declaration of getPtrFn as a pointer-to-Test-member-function taking no parameters (void) and returning void, so after you put the braces { ... } you get a compile-time error (its like trying to declare int i{/*some statemets*/}).
Also, and don't forget to keep the declaration
void(*getPtrFn(void))(void);
in your header (right now it seems you don't have it, did you cut/pasted it?).
Quite a horrible thing to look at... So really, use a type alias, it makes your code much cleaner.
using PTRFN = void(*)(void); // or typedef void(*PTRFN)(void);
class Test {
private:
PTRFN ptrFn;
public:
PTRFN getPtrFn(void);
Test(){};
~Test(){};
};
PTRFN Test::getPtrFn(void) // clear an concise
{
return ptrFn;
}
In case you really really want to be able do decipher every kind of pointer declaration you can think of, try looking at the clockwise/spiral rule, I found it extremely useful, clear and easy to understand. Then test your knowledge at cdecl.org.
I'm trying to call a function defined in a C file from my CPP code and I think I am having issues getting the correct namespace. When compiling I get the error: "Undefined reference to 'Get'".
My C header:
// c.h
#ifndef C_H
#define C_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
VAL_A1,
VAL_A2
} TYPE_A;
typedef enum
{
VAL_B1,
VAL_B2
} TYPE_B;
typedef enum
{
VAL_C1,
VAL_C2
} TYPE_C;
typedef struct
{
TYPE_B b;
TYPE_C c;
} TYPE_D;
TYPE_A Get(TYPE_B b, TYPE_D *d);
#ifdef __cplusplus
}
#endif
#endif
And my CPP file:
// main.cpp
...
extern "C" {
#include "c.h"
}
...
namespace MyNamespace
{
...
MyClass::MyFunc()
{
TYPE_D d;
// None of these calls will compile
// Get(VAL_B1, &d);
// ::Get(VAL_B1, &d);
}
...
}
I have tried calling without namespace reference and also with the "root" namespace using "::" with no luck. Any help is appreciated. I've read through this which seems to clarify it but I don't really understand it:
using C++ with namespace in C
"Undefined reference" means that the function has been declared (in the header), but not defined. You'll need to define the function in a source file somewhere (presumably the C file you refer to), and make sure that is linked when you build the program.
First, let's note what that error means. An undefined reference at the linker stage means that the compiler is unable to find the instance of something. In this case, the implementation of a function.
Let's look at your code.. There are a few things missing that we need to add to make it compilable:
A definition for Get().
main()
The class definition for MyClass.
Once we added those three fixes, the code compiles without error.
extern "C" { extern "C" {
typedef enum {
VAL_A1,
VAL_A2
} TYPE_A;
typedef enum {
VAL_B1,
VAL_B2
} TYPE_B;
typedef enum {
VAL_C1,
VAL_C2
} TYPE_C;
typedef struct {
TYPE_B b;
TYPE_C c;
} TYPE_D;
TYPE_A Get(TYPE_B b, TYPE_D *d) {
return VAL_A1;
}
}}
namespace MyNamespace {
struct MyClass {
void MyFunc();
};
void MyClass::MyFunc() {
TYPE_D d;
Get(VAL_B1, &d);
::Get(VAL_B1, &d);
}
}
int main() {}
The definition of Get (not shown in the question) also needs to be enclosed in extern "C".
The main difference between C and C++ functions, in practice, is the way they are named in the executable format. C++ functions get "name mangling" treatment by the linker but C functions do not. The linker will see the C++ definition of Get and it will have no idea of its relation to the C declaration, even if they have the same signature.
In one of my classes, I am trying to use std::priority queue with a specified lambda for comparison:
#pragma once
#include <queue>
#include <vector>
auto compare = [] (const int &a, const int &b) { return a > b; };
class foo
{
public:
foo() { };
~foo() { };
int bar();
private:
std::priority_queue< int, std::vector<int>, decltype(compare)> pq;
};
My program compiles perfectly until I add a .cpp file to accompany the header:
#include "foo.h"
int foo::bar()
{
return 0;
}
This time, my compiler generates an error:
>main.obj : error LNK2005: "class <lambda> compare" (?compare##3V<lambda>##A) already defined in foo.obj
Why can't I create a accompanying .cpp file if my header file contains a lambda?
Compiler: Visual Studio 2012
My main.cpp:
#include "foo.h"
int main(){
return 0;
}
As #Rapptz suggested,
const auto compare = [] (const int &a, const int &b) { return a > b; };
Solved the problem. Why?
Internal vs External linkage. By default, auto, like int has external linkage. So just how:
int j = 5;
In foo.h that would later be included by foo.cpp throws a
Error 2 error LNK2005: "int j" (?j##3HA) already defined in Header.obj
(VS 2013)
However, const makes the linkage internal by default, which means it is only accessible in one translation unit, thereby avoiding the problem.
I'm unable to replicate this problem for some reason. I'm trying this on VS2010 though - not sure if that made a difference. In fact, I tried including your header in two source files and it compiles, links and runs fine.
That said, do you want to consider using std::function. That way you can define the lambda in the cpp code and it won't get defined multiple times for whatever reason. (BTW, where's foo.obj coming from? Do you have another source file that is including this header ?).
foo.h:
#pragma once
#include <queue>
#include <vector>
#include <functional>
typedef std::function<bool (int, int) > comptype;
//auto compare = [] (const int &a, const int &b) { return a > b; };
class foo
{
public:
foo() { };
~foo() { };
int bar();
private:
std::priority_queue< int, std::vector<int>, comptype> pq;
};
Then later in the cpp include and define the lambda and when you create the pq pass it to the constructor.
foo.cpp:
auto compare = [] (const int &a, const int &b) { return a > b; };
foo::foo():pq(compare){}
This way you're deftly not defining the function multiple times.
class_one.h:
#ifndef CLASS_ONE
#define CLASS_ONE
#include <string>
namespace ones{
typedef enum{BLACK, WHITE, RED} b_color;
typedef char b_letter;
const b_letter letters[4] = {'A', 'B', 'C', 'D'};
class one{
b_color color;
b_letter letter;
public:
one(b_color, b_letter);
std::string combo();
b_color getColor();
b_letter getLetter();
};
}
#endif
Given this header file, how should I go about creating the .cpp file, and how then instantiate this class in another file, main.cpp?
I would think something like this:
class_one.cpp
#include <iostream>
#include "class_one.h"
using namespace ones;
class one
{
b_color color;
b_letter letter;
public:
one(b_color c, b_letter l) //Not sure about this one..
{
color = c;
letter = l;
}
std::string combo()
{
return "blahblah temporary. letter: " + letter; //not finished
}
b_color getColor()
{
return color;
}
b_letter getLetter()
{
return letter;
}
};
and then to instantiate it, I would do something like this:
main.cpp
#include "class_one.h"
int main()
{
ones::one test(ones::BLACK, ones::letters[0]);
//cout<<test.name()<<endl;
return 0;
}
Everything is extracted from a larger cluster of files, but this is the essentials of my question.. The header file should be correct, but I'm not sure how to instantiate the 'one' class, and not with that constructor. I think the constructor I defined in the .cpp is wrong. I'm used to Java, so I've never seen a constructor like the one in the header file, if it's even a constructor. To me it looks like method(int, int) instead of what I'm used to: method(int a, int b)
When running this I get this error:
main.obj : error LNK2019: unresolved external symbol "public: __thiscall ones::one::one(enum ones::b_color, char)" (??0one#ones##QAE#W4b_color#1#D#Z) referenced in function _main
<path>/project.exe : fatal error LNK1120: 1 unresolved externals
Sorry for the incredibly stupid naming I have here, but it does make sense for the purpose. May be some typing errors in the question codes as I've written most of this by hand right now.
Any help appreciated..
Your cpp file should look like this:
#include "class_one.h"
ones::one::one(ones::one::b_color c, ones::one::b_color l)
{
//code here
}
std::string ones::one::combo()
{
// code here
}
// additional functions...
And so on. You don't redefine the class with a class block, you just specify the individual function definitions like I showed here. The function definition format should be something like this:
[return type] [namespace]::[class]::[function]([parameters])
{
// code here
}
It looks like you're good on instantiation. You also don't have to redeclare the member variables.