is this possible:
changing a constant variable to non-constant
I am making a whole new string class and my constructor looks like this
LString(const char string1[]) {/* whatever I do */}
I wouldn't put the const keyword but that is the only way I can get strings like
LString ls = "a string";
I will have a lot of functions to modify this string
even though I make a copy of this string I still cannot convert const to non const
is it possible
if not, can anyone think of a loophole
ok so some people were saying that there is no problem, well here is my code
#include <iostream>
#include <cstdlib>
using namespace std;
class LString
{
public:
LString(const char string1[]){
char s1[250] = {string1};
cout << "you constructed LString with a const string as a parameter";
}
};
this comes up with the following errors
file.cpp: In constructor 'LString::LString(const char*)':
file.cpp:7:24: error: invalid conversion from 'const char*' to 'char'
if this makes a difference I am using the mingw compiler without an IDE
I am compiling through the command prompt
I think thats all the info you might need
tell me if you need anymore
Your constructor is fine - the input should be const.
The copy can be non-const, no problem.
#include <string.h>
class A {
public:
A(const char* string)
: a(strdup(string))
{}
char* a;
};
Here I'm using strdup to make a copy. What are you using?
I believe the compiler thinks you're trying to change the string you're assigning from. Since it can't be changed that's why it's complaining. Did you make a copy of the string to make changes to?
I don't see the problem. Keep the constructor signature as it is, but make the internal variable non-const and copy it over. Copy it at the start of the func and then work with that variable instead.
Related
Can you explain why the following code compiles and runs? What is the concept at play here, and what are the limitations/requirements for such a methodology to work?
class string_wrapper
{
public:
string_wrapper(string i_string);
string m_value;
int m_length;
};
string_wrapper::string_wrapper(string i_string)
{
m_value = i_string;
m_length = i_string.length();
}
void bar(string_wrapper i_param)
{
cout << i_param.m_value << std::endl;
}
void foo()
{
string test_string = "test1";
bar(test_string);
}
int main()
{
test_function_b();
}
Output:
test1
I would expect this code to not compile. foo() is passing a string parameter to bar(), when bar only takes a string_wrapper parameter. However, the compiler is smart enough to know that it can use the string parameter as a parameter to a constructor for a string_parameter object, which presumably is then passed on as the actual parameter to bar().
Is this behavior within the C++ standard, or unique to my compiler (Visual Studio 2017, version 15.9, in this case)? Any insight or terminology I can use for further research would be appreciated.
Whats going on here is implicit construction. You are right about the compiler being 'smart' enough to know that you can create a string_wrapper out of a std::string and so does it automatically for you.
To stop this happening you can use the explcit keyword like this:
...
explicit string_wrapper(string i_string);
...
The explicit keyword tells the compiler that you do not want it to automatically construct string_wrapper objects for you out of std::string's. This can stop hard to track down bugs because it prevents accidentally constructing objects (especially on function returns and when passing arguments).
Implicit construction can happen when an object has only one non-defaulted parameter (implicit conversion is something you should research as well). It can be a powerful tool and can allow things like proxy classes and transparent APIs (i.e std::vector's reference class). Generally you should declare single parameter (or single undefaulted value) constructors (and conversion operators) explicit unless you are making a design decision not too.
I wish to have a class in my program that directly takes the Command Line arguments from the main method. I want some of this information to be Constant to the Class, but also dependant upon the Command Line arguments that were entered.
I have read the detailed answer here:
C++ defining a constant member variable inside class constructor , however I am still a little confused...
main.cpp:
#include "Launcher.h"
int main(int argc, char *argv[]) {
Launcher launcher(argc, argv);
// do other stuff with launcher
return 0;
}
Launcher.h:
#ifndef LAUNCHER_H
#define LAUNCHER_H
#include <string>
#include <vector>
class Launcher {
public:
Launcher(int, char *[]);
private:
const int argumentCount;
const std::vector<std::string> arguments;
static const std::vector<std::string> INIT_arguments(int, char *[]);
};
#endif
Launcher.cpp
#include "Launcher.h"
Launcher::Launcher(int inputCount, char *inputArguments[]) :
argumentCount(inputCount),
arguments(INIT_arguments(inputCount, inputArguments))
{}
Launcher::INIT_arguments(int inputCount, char *inputArguments[]) {
std::vector<std::string> argumentVector;
for (int i = 0; i < inputCount; i++) {
std::string currentArgument = inputArguments[i];
argumentVector.push_back(currentArgument);
}
return argumentVector;
}
(I understand that in this example there may be alternative methods to achieve the same results by not using an initializer lists. In other cases I've used complex functions to determine the const variable's value but chose this simple example to demonstrate the concept.)
My questions are:
Are there any problems with initializing a const member variable by using a static function(In the example above)?
Does anything change / are there any more problems if the function used to initialize the const variable is non-static?
Is there any difference between defining the function in the header file alongside its declaration versus how its been declared in the header file then defined in the source file? Are there any differences if it's static/non-static?
Unrelated to the general question but... Is there an easy way to pass the char *[] variable by reference or perhaps a more efficient way?
Are there any problems with initializing a const member variable by using a static function(In the example above)?
No. One could argue that such a local helper function that has little to do with your actual class could instead be outsourced into a helper/utility entity, maybe a free function (template) in an anonymous namespace or somewhere else (to make it testable).
Does anything change / are there any more problems if the function used to initialize the const variable is non-static?
Making it static ensures that the member function has nothing to do with any of the instances' state (same for free functions, obviously). I would definitely keep it that way for functions that are used to initialize state.
Is there any difference between defining the function in the header file alongside its declaration versus how its been declared in the header file then defined in the source file?
No. If you would make it a free function though, you need to take care of possible ODR violations, and at least mark it as inline.
Is there an easy way to pass the char *[] variable by reference or perhaps a more efficient way?
There is a more efficient way, i.e., not using the function at all and rely on the std::vector constructor (overload #4) that takes two iterators as arguments. Pointers to the same raw array are fine here, so you can just do:
Launcher::Launcher(int inputCount, char *inputArguments[]) :
argumentCount(inputCount),
arguments(inputArguments, inputArguments + inputCount) {}
Note also that Launcher doesn't seem to intend modifying the command line arguments. In this case, you don't have to copy the strings at all. Use a std::string_view instead (if C++17 is available) or just leave it as const char* (one nice thing about command line arguments is that you don't have to think about their lifetime).
I have seen this question: Attempting to reference a deleted function (VS2013) but it didn't provide me an answer.
I have a member variable in class which its type is ofstream and a constructor which contains string parameter:
class dogs
{
public:
ofstream dogsFile;
dogs(string location)
{
}
};
The following error appears:
Error 2 error C2280: 'std::basic_ofstream>::basic_ofstream(const std::basic_ofstream> &)' : attempting to reference a deleted function c:\users\pc\documents\visual studio 2013\projects\database\database\database.cpp 26 1 Database
I have tried this code again but instead of using string I used char*:
class dogs
{
public:
ofstream dogsFile;
dogs(char* location)
{
}
};
And the error disappeared. Why? why does string makes the error?
Edit:
This is the whole code:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class dogs
{
ofstream dogsFile;
public:
dogs(string location)
{
}
};
int main(int argc, _TCHAR* argv[])
{
dogs dog = dogs("dog.bin");
return 1;
}
The original answer by Dieter seems to be correct.
I.e. This will compile:
dogs *dog = new dogs("dog.bin");
Your line will not, see his answer about copy constructors.
the dogs("dog.bin") will create an object then "=" will make a copy of it and give it to dog. Can't copy object with ofstream in it.
You can also fix this by using
dogs dog("dog.bin");
instead.
I can't think of this as anything else than a bug in VC++.
The way the dogs class is defined, the compiler should generate an implicit move constructor for it, which will call the move constructor for std::ofstream, which is defined as of C++11.
The rules for when to define an implicit move constructor are specified in the standard in [12.8/9] and [12.8/11]. They're also listed here. I can't see any reason not to declare the implicit move constructor in this case.
Then, the line
dogs dog = dogs("dog.bin");
must invoke a move from the temporary dogs object on the right hand side to the left-hand-side dog (the move may be elided, but the constructor needs to be accessible nonetheless).
In short, everything should work fine.
And it does in Clang 3.5. It doesn't work in GCC, but only because it doesn't have move constructors defined for stream classes (it's not standard-compliant in that respect).
Funnily enough, it works in VC++, as the OP duly mentioned, if the dogs constructor is declared to take anything else but a std::string by value. Change the constructor to any of the following:
dogs(const string& location)
or
dogs(int a) //And change the call accordingly, of course.
or
dogs(A a) //And change the call accordingly (A is a user-defined class).
and everything will work fine in VC++, as it should.
The fact that it doesn't work only for std::string passed by value seems to indicate there's a bug in the compiler. Basically, in that case, and only in that case, the compiler decides not to define the implicit move constructor, which causes the copy initialization to fall back to calling the copy constructor, which causes the error.
If you explicitly define the move constructor, like this:
dogs(dogs&& arg) : dogsFile(std::move(arg.dogsFile)) { }
again, everything works fine, including with the constructor taking a std::string by value.
I can't see any valid reason for VC++ to behave this way.
I am getting no appropriate default constructor available error with the following simple piece of code:
class A
{
public:
const string cs ;
};
void main()
{
A a;
return;
}
If I remove the const from string then code compiles fine. I can not understand why the default constructor is not getting created by compiler? And what is the deal with const string member variable?
I am working on VS2008.
As mentioned in the comments, const variables cannot be left unitialized in C++. There are two ways you can initialize your variable. In both cases, the content of the string can never be modified (as this is what const means).
1) In the class declaration. This method is useful only if you always want this string to have the same value across all of your objects. It is very inflexible and if you find yourself using it you should probably declare the variable as static.
class A
{
const string cs = "value of cs";
};
2) assign it in the constructor, using constructor chaining. This is much more flexible and idiomatic.
class A
{
const string cs;
public:
A() : cs("value of cs")
{
}
};
Note that this can be used with arguments, eg
A(string s) : cs(s) //initializes cs to the value of s
Your error probably arises from the compiler trying to find the second option.
Since C++17 it is legal to have a const member with no initializer -- if that member has a default constructor which initializes itself. void main() is still incorrect though!
So here is some valid code:
#include <string>
struct A { const std::string cs; };
int main()
{
A a;
}
The string a.cs is an empty string which is const.
If using an older compiler you will have to give a redundant initializer for cs.
Accidential use of classes inside of c style typeless variable arguments list is a common error source.
Example:
class MyString {
public:
char *pChars;
int Length;
MyString(char *pChars) {
this->pChars = pChars;
Length = strlen(pChars);
} };
int main() {
MyString s1("Bla1"), s2("Bla2");
printf("%s%s", s1, s2); // This does not but should give a compiler warning/error!
return 0; }
The printf call there receives the two s objects by value. that means all of their members are simply memory copied. But they are interpreted a simple char pointers. Result is a runtime error of course.
I am not asking for a solution to this, but I would like to have something I could add to my class so that the compiler warns me about it or gives an error.
Already tried to declarate but not implement a copy constructor. But it seems that no copy constructor is called. :-(
Please just answer to the question in the title. I do not need a discusson of why you should not use printf or these variable arguments lists - know that.
Thanks for your time.
Decent compilers (like gcc) check whether printf arguments match format specifiers in format string.
Just do not forget to add -Wformat or -Wall command line option.
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Derive from boost::noncopyable
Hide copy constructor and assignment operator (declare them private, no need to implement them). Or derive the class from boost::noncopyable (which has the same effect).Passing arguments by value determines the usage of the copy constructor.