I'm learning about constructors in C++, but the MSVS compiler is behaving strangely, and I don't understand why. The success of the compiler appears to be dependent on recent attempts at compilation. My expectation is that if my code successfully compiles once, it should always successfully compile, and if it gives an error, it should always give an error. With my code here, that is not the case. I'm using the debugger in the free MSVS 2019 IDE on Windows 10.
I have 3 files that form my project, and 3 different versions of the project I will call A, B, and C.
Version A is the code as presented in the first three displays below. I think version A should compile and run as I expect. Any actual errors in version A are probably secondary to this question. The code should define a class, create an instance of the class (running the constructor), call a method of the class, and finally call the destructor for that object when the program terminates.
The following code is in Cat.h.
#pragma once
#include <iostream>
class Cat {
private:
bool happy;
public:
Cat();
~Cat();
void meow();
};
The following is in file Cat.cpp.
#include <iostream>
#include "Cat.h"
Cat::Cat() {
std::cout << "Creating Cat" << std::endl;
happy = false;
};
Cat::~Cat() {
std::cout << "Deleting Cat..." << std::endl;
};
void Cat::meow() {
if (happy) {
std::cout << "Meow" << std::endl;
}
else
{
std::cout << "SSSSSsssss" << std::endl;
}
return;
};
The following is my main file.
#include "Cat.h"
int main() {
Cat cat;
cat.meow();
}
Version B is identical to version A, except with the one change that happy is declared in the constructor for Cat, making happy a local variable of the constructor.
Cat::Cat() {
std::cout << "Creating Cat" << std::endl;
bool happy = false;
}
Version C is identical to version A, except with the obvious error that the semicolon is removed after the class declaration in Cat.h.
Cat();
~Cat();
void meow();
}
Now for the weird behavior.
If I first attempt to compile version A, I get the following errors:
1>Debug\Cat.obj : warning LNK4042: object specified more than once; extras ignored
1>Source.obj : error LNK2019: unresolved external symbol "public: __thiscall Cat::Cat(void)" (??0Cat@@QAE@XZ) referenced in function _main
1>Source.obj : error LNK2019: unresolved external symbol "public: __thiscall Cat::~Cat(void)" (??1Cat@@QAE@XZ) referenced in function _main
1>Source.obj : error LNK2019: unresolved external symbol "public: void __thiscall Cat::meow(void)" (?meow@Cat@@QAEXXZ) referenced in function _main
If I now change version A to version B and compile, I get no errors, but the I'm not initializing happy in the constructor of cat. If I then change version B back to version A, the code compiles and runs as I expect.
Now version A compiles and runs, even though it is the same code that was giving me an error before.
If I now change version A to version C and compile, I get the obvious error:
1>Cat.cpp
error C2533: 'Cat::{ctor}': constructors not allowed a return type
1>Cat.h
fatal error C1004: unexpected end-of-file found
If I now change this version C to version A and compile, I get the same error that followed the initial compilation of version A. Reverting to version B and back fixes that problem.