Reputation: 46011
I've just started to learn C++ using Visual Studio 2019.
I'm trying to move the variable declaration from a class method to the header file. Originally, this is my class:
The header file:
#pragma once
#include <string>
class MyClass
{
public:
MyClass();
~MyClass();
bool Connect(std::string host, std::string port);
};
And the Cpp
file:
#include "MyClass.h"
#include "TelnetClient.h"
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
MyClass::MyClass()
{
}
MyClass::~MyClass()
{
}
bool MyClass::Connect(std::string host, std::string port)
{
// Omitted for brevety
// Create a Telnet client
TelnetClient telnet(io_service, iterator);
// Omitted for brevety
}
But, this version doesn't compile (here, I have moved telnet
declaration to the header file:
#pragma once
#include <string>
class TelnetClient;
class MyClass
{
public:
MyClass();
~MyClass();
bool Connect(std::string host, std::string port);
private:
TelnetClient telnet;
};
And the Cpp
file:
#include "MyClass.h"
#include "TelnetClient.h"
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
MyClass::MyClass()
{
}
MyClass::~MyClass()
{
}
bool MyClass::Connect(std::string host, std::string port)
{
// Omitted for brevety
// Create a Telnet client
telnet(io_service, iterator);
// Omitted for brevety
}
With this new version, I get two errors.
One, in the new header file:
telnet uses class 'TelnetClient' undefined.
And another one, inside the Cpp
file:
error C2064: the term is not evaluated as a function with 2 arguments
I have checked Constructors and member initializer lists, and they don't say how can I do it.
How can I instance the telnet
variable declared in the header file?
UPDATE:
I have updated the header file, removing the forward declaration and adding the #include "TelnetClient.h"
and, in the method, changed this:
telnet = TelnetClient(io_service, iterator);
And now I get two new error messages.
One, in the MyClass
constructor:
error C2512 'TelnetClient': no suitable default constructor available
And the second one in the new telnet = TelnetClient(...
:
error C2280 'TelnetClient & TelnetClient :: operator = (const TelnetClient &)': Attempting to reference a removed function.
Upvotes: 0
Views: 925
Reputation: 598414
In your .h
file, the compiler doesn't know what the TelnetClient
type looks like, as you are only forward declaring it, so you can't declare any instances of TelnetClient
in your header, only TelnetClient*
pointers and TelnetClient&
references. You would need to move the #include "TelnetClient.h"
statement from your .cpp
file into your .h
file, and get rid of the forward declaration.
Then, inside of your Connect()
method, you are still trying to call the TelnetClient
's constructor direct on the telnet
member, which won't work in that context anymore. But, you can create a new instance and move it into the existing instance.
For example:
#pragma once
#include <string>
#include "TelnetClient.h"
class MyClass
{
public:
MyClass();
~MyClass();
bool Connect(std::string host, std::string port);
private:
TelnetClient telnet;
};
#include "MyClass.h"
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
MyClass::MyClass()
{
}
MyClass::~MyClass()
{
}
bool MyClass::Connect(std::string host, std::string port)
{
// Omitted for brevety
// Create a Telnet client
telnet = TelnetClient(io_service, iterator);
// Omitted for brevety
}
UPDATE: Actually, this won't work in your case, because this error:
error C2512 'TelnetClient': no suitable default constructor available
means TelnetClient
does not have a parameter-less default constructor, so you can't construct a TelnetClient
object without passing parameters into its constructor. Which means if you intend to declare a TelnetClient
instance in your .h
file then you must use your MyClass
constructor's member initialization list to construct it with parameters. Also, because this error:
error C2280 'TelnetClient & TelnetClient :: operator = (const TelnetClient &)': Attempting to reference a removed function.
means that TelnetClient
has disabled its copy assignment operator, and doesn't have a move assignment operator, so telnet = TelnetClient(io_service, iterator)
will not work, either.
For example:
#pragma once
#include <string>
#include "TelnetClient.h"
class MyClass
{
public:
MyClass();
~MyClass();
bool Connect(std::string host, std::string port);
private:
TelnetClient telnet;
};
#include "MyClass.h"
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
MyClass::MyClass()
: telnet(io_service, iterator) // <-- you will have to get these params from somewhere, or pass them in to MyClass() itself
{
}
MyClass::~MyClass()
{
}
bool MyClass::Connect(std::string host, std::string port)
{
// Omitted for brevety
}
Otherwise, you will have to change the telnet
member to be a TelnetClient*
pointer instead, then you can continue using your forward declaration in the .h
file, and your Connect()
method can new
a TelnetClient
object using its 2-parameter constructor. But then you will have to update MyClass
to follow the Rule of 3/5/0 to manage that pointer correctly to avoid leaks and such.
For example:
#pragma once
#include <string>
class TelnetClient;
class MyClass
{
public:
MyClass();
MyClass(const MyClass &) = delete;
~MyClass();
MyClass& operator=(const MyClass &) = delete;
bool Connect(std::string host, std::string port);
private:
TelnetClient* telnet;
};
#include "MyClass.h"
#include "TelnetClient.h"
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
MyClass::MyClass()
: telnet(NULL)
{
}
MyClass::~MyClass()
{
delete telnet;
}
bool MyClass::Connect(std::string host, std::string port)
{
// Omitted for brevety
// Create a Telnet client
delete telnet;
telnet = new TelnetClient(io_service, iterator);
// Omitted for brevety
}
Upvotes: 1
Reputation: 123548
A forward declaration is not sufficient to declare a member variable. The definition of TelnetClient
must be available. Remove the forward declaration and include "TelnetClient.h"
in the header.
Members are initialized by the constructor not in arbitrary methods (actually before the constructor runs). When you want to assign a new instance to the member you need to use its operator=
(provided it has one) to assign a new instance:
bool MyClass::Connect(std::string host, std::string port)
{
// Omitted for brevety
// Create a new Telnet client
telnet = TelnetClient(io_service, iterator);
// Omitted for brevety
}
However, if possible you should properly construct the member in the contructor already:
MyClass::MyClass(io_service_t io_service, iterator_t iterator) : telnet(io_service,iterator)
{
}
Upvotes: 1