-1

Basically, i am quite new to c++ and i want to know why when i create an object it wont let me initialize it in the normal way. E.g 'int example = 10;' but when i try to initialize this problem like in the code below a problem comes up about some conversion:'no suitable constructor exists to convert from "const char [7]" to "binary"'.

#include <iostream>
using namespace std;
class binary
{
public:
    string value;

};
int main()
{
    binary first = "101010";
    return 0;
}
t.viney
  • 9
  • 2
  • There's probably a duplicate somewhere (looking for it).... Basically, the type of `"101010"` is `const char[7]`, not `std::string`. `binary first = "101010"` requires two implicit conversions (to `std::string`, then to `binary`) which is not allowed. – Justin Apr 19 '18 at 19:49
  • @Justin Even if you explicitly give a `std::string`, it still won't work. – François Andrieux Apr 19 '18 at 19:50
  • @FrançoisAndrieux Ahh, I usually don't construct my types with `type name = expr`; I usually use `type name{expr};`. – Justin Apr 19 '18 at 19:51
  • Close to a duplicate, but only addresses one of the problems: https://stackoverflow.com/q/44108754/1896169 – Justin Apr 19 '18 at 19:52
  • If you want to define a method of initializing your type, you must declare a [constructor](http://en.cppreference.com/w/cpp/language/initializer_list). There are some special cases, such as this one where aggregate types can be [aggregate initialized](http://en.cppreference.com/w/cpp/language/aggregate_initialization). In this case it would take the form of `binary first = { "101010" };`. – François Andrieux Apr 19 '18 at 19:52
  • 1
    Apart from anything else, if you use `std::string`, you need to `#include ` and not depend on `#include ` doing it for you. –  Apr 19 '18 at 19:53
  • Learn how constructor works, how copy/move assignment works. – greedy52 Apr 19 '18 at 20:42

3 Answers3

6

Neither

binary first = "101010";

nor

binary first = std::string("101010");

will work since the class does not have a constructor that takes such an argument.

You can use any one of the following:

binary first = {"101010"};
binary first = {std::string("101010")};
binary first{"101010"};
binary first{std::string("101010")};
Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

You can do field initialization like in the other answer, but if you're using a class, I'd recommend this for more control in the class itself on how it is created:

If the value should be initialized:

using std::string; //(not using namespace std;)
class binary
{
public:
  string value;
  explicit binary(string initialValue) :value(std::move(initialValue)) {}
private:
  binary() {} //optionally allow no initialization within class (see comments below)
};

int main()
{
  binary second("101010");
  return 0;
}

The empty private constructor allows the class itself to perform complex "initialization" of an instance outside the actual constructor. An example of such initialization could be reading an xml file and populating the class from the results (which could also be done by the class's client, or an Init() function within the class.) You can remove it if not needed. If it's optional to initialize from outside the class, you can move it into public:

zzxyz
  • 2,953
  • 1
  • 16
  • 31
  • 3
    There are problems with the code in this answer. `binary(string initialValue) :value(initialValue) {}` has no mention about `explicit` or not (that's *okay*, but worth mentioning), also makes an unnecessary copy of `initialValue` - you should use `:value(std::move(initialValue))`. Additionally, `private: binary() {} //explicitly prevent no initialization from outside the class` is wrong for 2 reasons: first, the default constructor is implicitly deleted because you have the `binary(string)` constructor already; second, you should use `= delete;` to delete functions – Justin Apr 19 '18 at 20:40
  • @Justin Did you read the last paragraph of my answer? Making the empty constructor private was not a delete attempt. I’ll check out the std::move thing when I’m back at my desk and probably update the answer. My use of STL definitely leaves something to be desired. I assume passing by ref would work as well? – zzxyz Apr 19 '18 at 20:48
  • I did read the last paragraph of your answer. I still don't understand what you mean there. It doesn't need a private default constructor to "put together an instance of itself however it likes." – Justin Apr 19 '18 at 20:57
  • 1
    Passing by reference does work, but it's suboptimal because it copies temporary objects as well. [This Q&A](https://stackoverflow.com/q/7592630/1896169) goes into some detail over it, but keep in mind that you [don't want to take parameters by value in setters](https://stackoverflow.com/a/46554916/1896169) – Justin Apr 19 '18 at 21:00
  • @Justin No clearly the class in the example does not. I was just putting it out there since he’s a new programmer and that’s probably not his actual class. Self-contained class-factories/singletons, etc. Anyway was trying to give all 3 options. – zzxyz Apr 19 '18 at 21:03
  • @Justin Awesome. Thanks for the comments. I’ll try to improve my answer with them shortly. – zzxyz Apr 19 '18 at 21:04
  • @Justin - Done -- I hope this improves my answer. If you think the empty constructor confuses the issue, I can just remove it entirely. I really think this is a better approach than field initialization for a class, which should manage its own data imo. – zzxyz Apr 19 '18 at 22:42
  • 1
    @Justin - Sorry for the comment barrage, but thanks for the constructive feedback. Not knowing about `explicit` had me pick up a copy of `Effective Modern C++`. Sincerely appreciated. – zzxyz Apr 20 '18 at 00:10
-2

When you do

binary first

it creates an object named "first". You need to initialize "value" inside "first" like this:

binary first;
first.value = "101010";

If I remember correctly, C++ will implicitly convert your char[7] to a string

Richard Hum
  • 651
  • 2
  • 6
  • 14
  • 2
    That does not initialise `value`, it assigns to it. –  Apr 19 '18 at 19:53
  • The form `T foo = bar;` creates a `T` named `foo` directly from `bar`. It's not the same as creating a `T` then assigning `bar` to it. – François Andrieux Apr 19 '18 at 19:54
  • I've heard and seen constructors, but how in the constructor can i make the conversion since it runs when the object is created, not specifically when it is initialized. – t.viney Apr 19 '18 at 19:57
  • @t.viney Object creation is object initialisation. –  Apr 19 '18 at 20:00