I'm not too familiar with c++ and how instantiating objects work, so this is probably a very simple thing to solve. When I compile with g++ I get the error " undefined reference to 'Foo::Foo(std::string)' ". I want to create an instance of the class Foo that has a string parameter in its constructor. Here is the code:
Foo.h
#include <string>
using namespace std;
class Foo
{
public:
Foo(string s);
private:
string id;
};
Foo.cpp
#include <string>
#include "Foo.h"
using namespace std;
Foo::Foo(string s)
{
id = s;
}
main.cpp
#include <string>
#include "Foo.h"
using namespace std;
int main()
{
Foo foo("bar");
return 0;
}
You're probably not including Foo.cpp in your compile line. It should look something like this:
g++ main.cpp Foo.cpp -o testFoo
Not related to the problem you were having but consider making a couple minor changes:
Pass the argument in a const reference. const because you do not plan on changing the value of the argument and reference so that you do not create any additional temporary objects.
C++ has an initializer concept that is more efficient then using the assignment operator on member 'id' in the body of the constructor. The current version of the constructor will call member id's default constructor and then its assignment constructor. The initializer concept (i.e. 'id(s)') will just call one method the copy constructor.
Foo::Foo(const string& s) : id(s)
{
}
Related
I'm getting the following error during compilation:
Severity Code Description Project File Line Suppression State
Error C2664 'mytest::Test::Test(const mytest::Test &)': cannot convert argument 1 from '_Ty' to 'const mytest::Test &' TotalTest C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xutility 158
I have no idea what is, so I'm putting the code here to exemplify what was being done:
TotalTest.cpp
include <iostream>
#include "Test.h"
using namespace mytest;
int main()
{
std::cout << "Hello World!\n";
new Test();
}
Test.h
#pragma once
#include "Test.h"
#include <iostream>
namespace mytest
{
using namespace std;
class Test
{
public:
Test();
~Test();
shared_ptr<Test> t;
};
}
Test.cpp
#include "Test.h"
namespace mytest
{
Test::Test()
{
}
Test::~Test()
{
}
}
TestFactory.h
#pragma once
#include "Test.h"
#include <iostream>
namespace mytest
{
using namespace std;
class TestFactory
{
public:
TestFactory();
shared_ptr<Test> CreateTest(int testClass);
};
}
TestFactory.cpp
#include "TestFactory.h"
namespace mytest
{
TestFactory::TestFactory()
{
}
shared_ptr<Test> TestFactory::CreateTest(int testClass)
{
return make_shared<Test>(new Test());
}
}
I'm using Visual Studio C++ language standard: ISO C++14 Standard (/std:c++14)
In TestFactory::CreateTest(), make_shared<Test>(new Test()) is wrong, as Test does not have a constructor that accepts a Test* pointer as input.
You need to use make_shared<Test>() instead, letting make_shared() call the default Test() constructor for you:
shared_ptr<Test> TestFactory::CreateTest(int testClass)
{
return make_shared<Test>();
}
Any parameters you pass to make_shared() are passed to the constructor of the type specified in the template argument. In this case, there are no parameters needed.
The error comes from the following line:
return make_shared<Test>(new Test());
There are 2 ways of initializing a std::shared_ptr:
Using the std::shared_ptr constructor directly, which requires you to pass a Test object already allocated on the heap, e.g.:
std::shared_ptr<Test> p{ new Test() };
Using make_shared(), which performs the heap allocation internally, e.g.:
std::shared_ptr<Test> p{ std::make_shared<Test>() };
Where in the parentheses you can pass parameters to the constructor of Test.
The 2nd option is usually prefered. You can see more info here: Difference in make_shared and normal shared_ptr in C++
In addition:
Test.h should not include itself (it has #include "Test.h" at the top).
You should avoid using using namespace std;. More info here: Why is "using namespace std;" considered bad practice?
I am learning about smart pointers and when trying to compile the following "stupid" code I get an error.
#include <memory>
#include <iostream>
class Test
{
std::string myString="dumm";
};
int main()
{
std::unique_ptr<Test> test(new Test());
std::cout<<test->myString<<std::endl;
return 0;
}
I just wanted to see, whether this works but I get :"Applying -> to std::unique_ptr instead of a pointer", which seems weird.
I am using c++ 11
Eit: The error is now fixed and I cancompile the above code. However, CLion still gives me "Cant apply -> to std::uniq_ptr"-stuff, which seems to be an error with the IDE
In a class the default visibility is private which makes the myString field invisible to the test object. Make it public:
#include <iostream>
#include <memory>
#include <string>
class Test {
public:
std::string myString = "dumm";
};
int main() {
std::unique_ptr<Test> test(new Test());
std::cout << test->myString;
}
Prefer std::make_unique to direct use of new if compiling for C++14 and later:
std::unique_ptr<Test> test = std::make_unique<Test>();
This function is not available in the C++11 standard which is what you are using.
I'm trying to use arrays with unique_ptr with no success.
What is the correct way to declare a unique_ptr of some size?
(size is some paramter).
unique_ptr<A[]> ptr = make_unique<A[]>(size);
Here's an example:
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <memory>
using namespace std;
class A {
string str;
public:
A(string _str): str(_str) {}
string getStr() {
return str;
}
};
int main()
{
unique_ptr<A[]> ptr = make_unique<A[]>(3);
}
This is not working, however, if I delete the constructor of A, it works.
I want the 3 to represent the size of the array, and not an argument to A's constructor, how do I make that happen?
This is not working, however, if I delete the constructor of A, it
works.
When you removed the user defined constructor, the compiler implicitly generates a default one. When you provide a user defined constructor, the compiler doesn't implicitly generate a default constructor.
std::make_unique<T[]> requires the use of default constructors...
So, provide one, and all should work well
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <memory>
using namespace std;
class A {
string str;
public:
A() = default;
A(string _str): str(_str) {}
string getStr() {
return str;
}
};
int main()
{
unique_ptr<A[]> ptr = make_unique<A[]>(3);
}
This is a noob question, sorry, I'm coming from Java and have no idea why my OO stuff isn't working. I have this main:
#include <iostream>
#include "Foo.h" //changed name
using namespace std;
int main(int argc, char*argv[])
{
int choice;
cin >> choice;
Foo net;
switch(choice)
{
case 1: net.buildNetwork(); break;
}
}
This Foo.h file:
#ifndef FOO_H
#define FOO_H
#include <iostream>
struct City{
std::string cityName;
std::string message;
City *next;
City(){}; // default constructor
City(std::string initName, City *initNext, std::string initMessage)
{
cityName = initName;
next = initNext;
message = initMessage;
}
};
class Foo
{
public:
Foo();
~Foo();
void addCity(std::string, std::string);
void buildNetwork();
void transmitMsg(char *); //this is like a string
void printNetwork();
protected:
private:
City *head;
City *tail;
};
#endif // FOO_H
And this Foo.cpp file, all in the same directory:
#include "Foo.h"
#include <iostream>
using namespace std;
Foo::Foo()
{
head = tail = NULL;
}
Foo::~Foo(){}
void Foo::buildNetwork()
{
cout << "works" << endl;
}
void Foo::transmitMsg(){}
void Foo::printNetwork(){}
void Foo::addCity(){}
When I compile, I get
/tmp/ccNx3fY5.o: In function `main':
main.cpp:(.text+0x38): undefined reference to `Foo::Foo()'
main.cpp:(.text+0x4c): undefined reference to `Foo::buildNetwork()'
main.cpp:(.text+0x59): undefined reference to `Foo::~Foo()'
main.cpp:(.text+0x7e): undefined reference to `Foo::~Foo()'
collect2: error: ld returned 1 exit status
What's wrong? Also, another question: in Foo.cpp, why do I need Foo::Foo() etc? I used namespace std, so why can't I just say Foo()?
Looking at the way you compile, you are only providing only one source file (main.cpp) whereas the correct way is to specify all the source files. In your case, it would be:
g++ main.cpp foo.cpp -o executable
The "undefined reference" error is a error thrown at the linking stage when the linker can't resolve the names correctly because, you didn't link the source files properly like above.
Additionally, make sure that when you declare a function prototype, the implementation of the function should also have the same signature. In your example, you provided the function prototypes as:
void transmitMsg(char *);
void addCity(std::string, std::string);
But your implementation of those functions don't have the correct signature. They should have been:
void Foo::transmitMsg(char *){}
void Foo::addCity(std::string, std::string){}
why do I need Foo::Foo() etc?
Because Foo() is a function of the class Foo.
I used namespace std, so why can't I just say Foo()?
When you make a call to using namespace ; all symbols in that namespace will become visible without adding the namespace prefix. A symbol may be for instance a function, class or a variable.
Foo is not a namespace like "std". It is a user-defined class.
Also, another question: in Foo.cpp, why do I need Foo::Foo() etc? I
used namespace std, so why can't I just say Foo()?
You need to write Foo::Foo() in foo.cpp because you are defining the constructor outside the body of the Foo class which is present in foo.h.
std is the standard namespace and using that in no way absolves you from referring to the Foo class you have created since its not a part of the standard namespace
You have not included foo.cpp in your compile command, So this is why you cant link the functions. You need to use the command line argument:
g++ main.cpp foo.cpp -o main
This allows the compiler to find the functions in foo.cpp.
Having a program like this:
#include <iostream>
#include <string>
using namespace std;
class test
{
public:
test(std::string s):str(s){};
private:
std::string str;
};
class test1
{
public:
test tst_("Hi");
};
int main()
{
return 1;
}
…why am I getting the following when I execute
g++ main.cpp
main.cpp:16:12: error: expected identifier before string constant
main.cpp:16:12: error: expected ‘,’ or ‘...’ before string constant
You can not initialize tst_ where you declare it. This can only be done for static const primitive types. Instead you will need to have a constructor for class test1.
EDIT: below, you will see a working example I did in ideone.com. Note a few changes I did. First, it is better to have the constructor of test take a const reference to string to avoid copying. Second, if the program succeeds you should return 0 not 1 (with return 1 you get a runtime error in ideone).
#include <iostream>
#include <string>
using namespace std;
class test
{
public:
test(const std::string& s):str(s){};
private:
std::string str;
};
class test1
{
public:
test1() : tst_("Hi") {}
test tst_;
};
int main()
{
return 0;
}
There is another and more simplified way of doing what you want:Just change your statement from test tst_("Hi"); to test tst_{"Hi"}; and it will work. Below is the modified code and it works as expected.
#include <iostream>
#include <string>
using namespace std;
class test
{
public:
test(std::string s):str(s){cout<<"str is: "<<s;}
private:
std::string str;
};
class test1
{
public:
test tst_{"Hi"};
};
int main()
{ test1 obj;
return 0;
}
Note that i have just changed test tst_("Hi"); to test tst_{"Hi"}; and everything else is exactly the same. Just for confirmation that this works i have added one cout to check that it initialize the str variable correctly. I think this one line solution is more elegant(at least to me) and and up to date with the new standard.