Weird default constructor

Pages: 12
I am trying to write a tic-tac-toe program using a class, and I got this example off a different internet forum, but it won't compile. Instead, it gives me this error:
In file included from tictactoe.cc:5:
./tictactoe.h:31:14: error: expected '('
: squareArray{'1','2','3','4','5','6','7','8','9'},
             ^ 

Here's the line of code that it's talking about:

1
2
3
4
5
6
7
8
9
10
// This looks really odd-I've never seen anything like it before.
// A friend suggested it might be an intentional error, and his reason was
// "script kiddies." I'm no expert, but I think it would be hard to use a 
// simple tic-tac-toe program for hacking??? 

TicTacToe::TicTacToe()
: squareArray{'1','2','3','4','5','6','7','8','9'},
  moveCounter(0)
{
}


It's also giving me this error:
In file included from tictactoe.cc:5:
./tictactoe.h:31:51: error: expected unqualified-id
: squareArray{'1','2','3','4','5','6','7','8','9'},
                                                  ^   

on the same line of code.
Can anyone tell me what is going on here? I've never seen anyone initialize a default constructor like that before.

Thanks!
max

Edit:
I'm wondering if he meant to put squareArray inside the constructor, along with the call to moveCounter...
Yeah, Im pretty sure thats it, because moveCounter and squareArray are both defined in the class.

1
2
3
private:
      char squareArray[9];
      int moveCounter;

That's weird that it's a c-string but he initialized it with a bunch of integers...maybe it would be better as an array of ints. Also, just noticed, he forgot about the null terminator!!
Last edited on
This is the same as your last problem.
You need to learn to compile as C++11.
I think it's the way he wrote it. Is that a valid default constructor?

Edit:
I guess it is??? I compiled it and set a -std=c++11 flag, and it compiled! Now to test it...

Edit 2:
We have a small issue now, I realize that it actually was three separate files-the driver program file, the header file, and the class implementation file. Sooo, since I don't have an IDE to automatically link them all together, I'm going to have to use a makefile to combine the stupid things. I don't see why people can't just chunk it all into one big file and compile it from the command line. I'm kidding, I know why, but it still ticks me off because I have to do everything from the command line.

Edit 3:
Ok, nevermind, I figured out how to compile all three of them directly form the command line.
But thanks, @dutch, for suggesting that I compile it as C++11 (with the -std=c++11 flag), that got rid of all the errors! I will use that flag in the future for compiling.

Thanks!
max
Last edited on
Is that a valid default constructor?

Yes, it's totally valid.

along with the call to moveCounter

It's not exactly a "call" since moveCounter is an int. It's just setting it to 0.

it's a c-string but he initialized it with a bunch of integers

They aren't integers. They are character digits. That's why they're in single quotes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

class TicTacToe
{
    char squareArray[9];
    int moveCounter;
public:
    TicTacToe();
    void print() const;
};

TicTacToe::TicTacToe()
    : squareArray{'1','2','3','4','5','6','7','8','9'},
      moveCounter(0)
{
}

void TicTacToe::print() const
{
    for (int i = 0; i < 9; ++i)
    {
        std::cout << squareArray[i] << ' ';
        if (i % 3 == 2) std::cout << '\n';
    }
    std::cout << "moveCounter: " << moveCounter << '\n';
}

int main()
{
    TicTacToe ttt;
    ttt.print();
}

Remember to compile as C++11 (at least) and to use full warnings:
g++ -std=c++11 -Wall -Wextra -pedantic ttt.cpp

(or clang++ instead of g++)
Last edited on
Careful! -W turns off all warnings
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
(Did you mean -Wextra?)
Last edited on
Careful! -W turns off all warnings

-W is exactly equivalent to -Wextra.
-w (small w) inhibits warnings.

-w

Inhibit all warning messages.

-Wextra

This enables some extra warning flags that are not enabled by -Wall. (This option used to be called -W. The older name is still supported, but the newer name is more descriptive.)

Still, I probably should've put -Wextra anyway, just to make it extra clear.
I'm going to edit the above to -Wextra.
Last edited on
@dutch,
What I meant was, he initialized it with a bunch of numbers, and I figured if you're going to make a c-string with numbers, you might as well use an array.

I use clang++ (c++ in the command line) for compiling. But when I use the -std=c++17 flag, I don't see the warnings anymore, so I don't really need to use -Wextra or -Wall.

Also, I just have never seen a default constructor defined like that before. Are there any good tutorials that teach how to do that kind of thing?

max
Thanks a lot @dutch, I didn't know. I'll have to pick out a better font.
@mbozzi, I'm glad you pointed it out. I'd never head of -w (little w). I'm going to write -Wextra from now on. It's kind of silly to just write -W now that I think about it.


@secret_agent_man, https://www.youtube.com/watch?v=PLauCeijmnU

I figured if you're going to make a c-string with numbers, you might as well use an array.

Presumably the program will put 'X' and 'O' into those positions as the game goes along. The digits are there to indicate to the user how to select the various positions. So they really are just characters, not numbers (no arithmetic will be done on them, for instance).

when I use the -std=c++17 flag, I don't see the warnings anymore, so I don't really need to use -Wextra or -Wall.

The point of -Wall and -Wextra (and -Wpedantic or the equivalent -pedantic) is to show more warnings than the default. So to say you don't get any warnings without them is kind of meaningless. I always use them.

I just have never seen a default constructor defined like that before. Are there any good tutorials that teach how to do that kind of thing?

I don't know exactly what you are talking about (maybe you are talking about the "member initializer list" between the colon and the opening brace) but I'm sure any modern book will explain constructors.
Last edited on
Oh, of course! I didn't think about it being a member init list. I haven't used them very often. And yes, I see you're right about the X and O's replacing the numbers, looking at the program I can see that now.

Why would I want more warnings? I mean, ok, if the warning's going to affect the running of the program, I want to know about it, but if it's just warning me that "something is a C++11 extension" then that's not really a big deal, right?
Why would I want more warnings? I mean, ok, if the warning's going to affect the running of the program, I want to know about it, but if it's just warning me that "something is a C++11 extension" then that's not really a big deal, right?


Wrong.

A lot of warnings indicate code that is "correct" and will compile, but may not do what you want. if (a = 5) {/* do something */} is legal and will compile, but it is actually assigning 5 to a and then always entering the code block. There are many subtleties like this that a compiler can catch for you if you pay attention to the warnings.

Many companies require warnings turned up to the highest level and require their programmers to have as few warnings in their builds (preferably 0) as possible. What is particularly bad is when developers decide that certain warnings are acceptable and they get ignored. However, warnings that are important get hidden by a flood of "unimportant" warnings, and a bug slips through. So, best practice is to get rid of all of the warnings.

You should not get used to extensions to the language. One compiler might allow an extension that you get used to, but parts of your project get reused on a new project that uses a different compiler. Now you have to spend days cleaning up build errors that were flagged as warnings in the old project.

I highly recommend you make a point of getting rid of all warnings that you can. This will save you in the long run.
Ah, I see. Thanks for clarifying, @doug4. I do pay attention to warnings like if (a = 5) and things like that. But, what do you mean by extensions to the language? I thought they were just newer versions of it?
This is my understanding of what is meant by extensions to the language. Others here can correct me if I am mistaken.

int main() {}

void main() {} // extension

The C++ standard states that main() must return int. Before standardization, many compilers allowed main() to return void. Because of legacy code, some compilers continue to allow main() to return void. This is an extension to the language.

int array[5];

1
2
int total = getTotalElements();
int array[total];   // extension 


The C++ standard does not allow Variable Length Arrays (VAR). All statically allocated arrays must have a constant size known at compile time. Some compilers, evidently, allow VARs as an extension.
Also,

I do pay attention to warnings like if (a = 5) and things like that.


Note comment from my previous post:

What is particularly bad is when developers decide that certain warnings are acceptable and they get ignored. However, warnings that are important get hidden by a flood of "unimportant" warnings, and a bug slips through.


I've been involved with projects that contained hundreds of "acceptable" warnings. When a new warning popped up, it was never seen. If you have more than a handful of expected warnings, how do you know that you will catch the "if (a = 5)" warning when it appears?

There is always* a way to clean up your code to get rid of warnings. You should just get in the habit of doing so from the get go.

* There may be extremely rare cases where it is not possible or extremely contrived to code against a warning. If that is the case:
1. You probably need to redesign the code
2. Add a comment to the code indicating the reason why the comment could not be removed.
With VS (and other compilers?), you can specify that the compiler ignores and doesn't report specified warning numbers - either for a compilation unit (not recommended) or for a specific section of code. If the warnings from specific code are to be accepted and ignored by the compiler, then new warnings are much easier to spot.

All our code must compile without any warnings at L4. All casts and suppression of compiler warnings must be reviewed and agreed.

Last edited on
@seeplus
Well, I don't use an IDE so I don't think I can specify it to ignore warnings except with a "-W" flag in the command line. I'm not sure what you mean by L4. Is it something in Microsoft VS?

@doug4
I am in the habit of checking my code over before compiling, to make sure there aren't any mistakes, but I do miss them sometimes. I think my compiler allows VAR's, but I never use them because I am aware of the terrible things they can do to your memory. And I had no idea that you could declare main as void! That's really weird, because, how can you return 0 from main if the return type is void?
I'm not sure what you mean by L4. Is it something in Microsoft VS?


Yes. It's level 4 warning (highest level).
I am in the habit of checking my code over before compiling, to make sure there aren't any mistakes, but I do miss them sometimes. I think my compiler allows VAR's, but I never use them because I am aware of the terrible things they can do to your memory. And I had no idea that you could declare main as void! That's really weird, because, how can you return 0 from main if the return type is void?


First, an apology. I meant VLA, not VAR. VAR is some acronym here at work that I typed out of habit. It looked really weird in your response :-)

Second, everything you typed here supports removing as many warnings as possible. You will miss some with a reading. It happens. You might accidentally code up something that is illegal, but is supported by an extension. Humans make mistakes. Compilers do a whole lot better flagging erroneous code.

As far as returning void--I don't think I've ever done that, but I believe you just wouldn't have a return statement in main. Actually, a return statement in main is optional (at least it used to be). The standard says that a program that exits main without a return statement will actually return 0. So, returning void was probably just a subset of that. But the point is, this is an extension, and not every compiler supports it. Let warnings tell you that you have potentially illegal code, and fix it.

Out of curiosity, have you changed your mind on this at all? Have I / we convinced you to clean up your warnings?
Last edited on
@doug4,
Thanks, I didn't even notice that I typed VAR instead of VLA (which I think means variable-length-array)!

I'm kind of confused...you said earlier that
There is always a way to clean up your code to get rid of warnings. You should just get in the habit of doing so from the get go.
but then you say that
You might accidentally code up something that is illegal, but is supported by an extension. Humans make mistakes. Compilers do a whole lot better flagging erroneous code.
I took that to mean that warnings are necessary to tell when you make mistakes. But, if warnings are so important, why would I want to get rid of them?

I was just wondering though, what does VAR stand for? If you can't tell me, thats ok, I was just curious.

Edit:
I'm still wondering, sometimes my compiler (LLVM clang-1000.10.44.4) gives me an error instead of a warning, like if I try to initialize a variable like this
 
double d1 {34.56};

then it gives me an error that says
pr2.cc:6:11: error: expected ';' at end of declaration
        double d1 {34.56};
                 ^
                 ;

But it doesn't give me a warning that its a C++11 extension (which I think it is).
Last edited on
But, if warnings are so important, why would I want to get rid of them?

You want to make your compiler display as many warnings as possible.

Then you want to improve your code to fix the things that are causing the warnings, so that there are no more things for the compiler to warn you about.

Pages: 12