Reputation: 1929
Say I have a header file:
class.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class my_class
{
private:
string var1;
public:
my_class(string var1_val) { var1 = var1_val; };
};
I wish to declare a my_class
variable as a global so it can be used across functions. However, it cannot be initialised outside the main function, as it requires user input to initialise. This poses a problem, as if the below code is run, I get: 'my_class': no appropriate default constructor available
source.cpp
#include <iostream>
#include <string>
#include "classes.h"
using namespace std;
my_class f;
int main(){
string inpt;
cout << "Enter var1 value: ";
cin >> inpt;
f = my_class(inpt);
}
How would I define the variable f
so I could initialise it in main
, but also use it in another function in the source.cpp
file?
Upvotes: 0
Views: 1026
Reputation: 114461
That is not directly possible... a global class instance requires initialization (only types like int
or double
can be left initialized, but only in local scopes - as global they're always initialized - and this possibility of leaving variables uninitialized is also something many think is a design error of the C++ language - most younger languages do not provide this option as experience taught us that it's a source of nasty bugs and provides no real advantage).
What you want to do could be interpreted as a variation on what is normally called the "singleton pattern" ... i.e. providing all the modules access to a single instance of a class.
This in C++ is normally done using a function that returns a reference to the variable... for example:
------------------------------------------------------------ parms.h
...
struct Parms {
std::string user_name;
int user_age;
static Parms& get(); // Providing access to the singleton
};
-------------------------------------------------------- module1.cpp
#include "parms.h"
...
void foo() {
// access the singleton
std::cout << "Hello " << Parms::get().user_name << "\n";
}
---------------------------------------------------------- parms.cpp
#include "parms.h"
...
static Parms* parmsp;
void init_parms(const std::string& user_name, int user_age) {
// creates the singleton
parmsp = new Parms{user_name, user_age};
}
Parms& Parms::get() {
// Provide access to the singleton
if (!parmsp) {
throw std::runtime_error("Parameters not yet initialized");
}
return *parmsp;
}
Upvotes: 0
Reputation: 5856
There are a few things mixed in the question. I'll try to address them individually.
The error message about the default constructor is exactly that: you are asking to instantiate an instance of that class but you only provide one way of doing so: the constructor with a string
parameter.
Two ways you can deal with that "directly":
string
parameter optional, like my_class(string var1_val = {})
my_class f{""};
Have a variable "outside" in the global scope but initialized in main()
... Also, a few ways to deal with that (personally I would advise against such a practice for various reasons, but providing options here for completeness):
my_class * f{nullptr};
or, even better, as a smart pointer: std::unique_ptr<my_class> f;
and instantiate the object in your main as either a naked pointer f = new my_class("string");
or a smart pointer f = std::make_unique<my_class>("args");
main()
and pass it into whatever function you need it inYou might also look into using a Singleton Pattern where you have a factory function that manages your f
(again, a horrible idea in this case, but providing it for completeness):
my_class & get_my_class(string s = {}){
static my_class * mc{nullptr};
if(!mc){ mc = new my_class{s}; } // <-- memory leak here unless you use unique_ptr
return *mc;
}
int main(){
// ...
auto & m{get_my_class("user input")};
// ...
}
void other_function(){
auto & f{get_my_class()};
// use f
}
Upvotes: 2
Reputation: 99
Just do this
my_class(string var1_val="") { var1 = var1_val; };
Provide default argument & you are good to go. Just to get the compiler to shut up. Although using global object is not a good solution.
Upvotes: 0
Reputation: 161
The problem that you describe
as if the below code is run, I get: 'my_class': no appropriate default constructor available
is because you have declare another constructor with some parameter. In this case, compiler will not generate default constructor. You have to do it by yourself. so the class should look like:
class my_class
{
private:
string var1;
public:
my_class(){};
explicit my_class(string var1_val) :
var1(var1_val)
{};
};
Good practice is when you are making constructor with one argument mark it as explicit
. Another good practice is to assign variables in constructor initialization list.
Best Regards
Upvotes: 0