1

I am attempting to connect to Sql Server with c++ using sqlapi++. I have gotten my code to work properly in my main function and when I am not instantiating an object within a class, but when I try to move my code over to a separate class I get errors.

The errors I'm getting are:

Expected a type specifier

and

syntax error: '&'

The code that produces the error is:

#include <string>
#include <SQLAPI.h>

class DbConnection
{
    SAConnection con;
    SACommand cmd(&con); //this line throws the error

    public:
       int age, id;

    void Connect()
    {
         con.Connect(
            "databaseName",
            "userName",
            "password",
            SA_SQLServer_Client);
    }
    void Retrieve()
    {
        cmd.setCommandText("SELECT * FROM [dbo].[TableName]");
    }
};

When I move the SAConnection and SACommand objects outside of the class DbConnection, the errors go away and it seems to work.

#include <string>
#include <SQLAPI.h>

SAConnection con;
SACommand cmd(&con);

class DbConnection
{
    //remaining code
};

I am having a difficult time understanding why that is, coming from other languages where I can instantiate and declare an object inside of a class is normal. I am missing some information, any explanation would be helpful.

Why can I not declare a class inside of another class?

xtryingx
  • 152
  • 7
  • 1
    *I am having a difficult time understanding why that is, coming from other languages where I can instantiate and declare an object inside of a class is normal.* -- Use the [member initialization list](https://stackoverflow.com/questions/7665021/c-member-initialization-list) in C++. Also, do not write C++ code using other languages as a model. – PaulMcKenzie Apr 29 '21 at 04:26
  • 1
    It's just the syntax that's wrong. You can't use `()` to do initialization inside the class definition. You need to use `= value;` or `{}`. – super Apr 29 '21 at 04:33
  • Okay I use `SACommand sqlCmd = SACommand(&sqlCon);` inside my class and that removed the errors. I assumed thats what you meant by `= value;`? Right? – xtryingx Apr 29 '21 at 04:37
  • So it seems like inside of the class the object will need to be instantiated when it is declared rather than simply declaring. Is this correcT? – xtryingx Apr 29 '21 at 04:38
  • 2
    @xtryingx Like super mentioned `SACommand cmd = &con;` valid and `SACommand cmd{&con};` also valid. https://godbolt.org/z/GedcYqf8E – Ch3steR Apr 29 '21 at 04:40
  • Alright, I think I am overcomplicating things. The answer posted helps, and also the comments help, it seems like it is just a syntax problem thats giving me problems and not much deeper than that. Thanks @super – xtryingx Apr 29 '21 at 04:45
  • Parentheses initializer cannot be used in the class definition, but you can use braced initializer – M.M Apr 29 '21 at 04:51

3 Answers3

1

Initializing cmd in a constructor is an easy way to understand class initialization. Something like this:

class DbConnection
{
    SAConnection con;
    SACommand cmd;   // this is just a declaration
    int age;
    int id;

public:
    // this is the constructor
    DbConnection()
        : con()
        , cmd(&con)  // here you initialize it
        , age(0)
        , id(0)
    {
    }
    ...
};

cmd is a member of your DbConnection class; its type is SACommand. When an instance of the class DbConnection is constructed, the constructor gets called, and it creates cmd, an instance of SACommand. It creates it by calling its constructor and passing it a reference to its SAConnection member: SACommand(&con).

EDIT (to answer the question in the comments section):

A class is a way to group, encapsulate, related data and its related operations. In particular, your DbConnection class encapsulates 4 data members: con, cmd, age and id. It just groups them together. It doesn't inherit them. The constructor is just a member function which job is to initialize the class, and part of initializing the class is to initialize all of its data members by calling their own constructors. Therefore, when you create/instantiate a new DbConnection class, it internally creates its 4 new data members and initializes them. If you were to create another instance of DbConnection, it will create its own 4 new internal members, independent of the ones belonging to the first instance of the class.

EDIT #2

As indicated in some of the comments, class data members can be initialized where they are declared since C++11. If you're interested in learning more details, I suggest googling "C++ In-class member initialization." There have been several initialization features on different C++ standards.

Luis Guzman
  • 996
  • 5
  • 8
  • Okay, so am I correct in saying that when I want to instantiate an object within a class, my constructor needs to inherit the object that I am instantiating? – xtryingx Apr 29 '21 at 04:41
  • No. The constructor is a especial class function which job is to initialize the class. I added another paragraph to the answer to expand on what the constructor does. – Luis Guzman Apr 29 '21 at 05:11
  • "You cannot instantiate cmd where you're declaring it as a class member", this is not correct unfortunatly... – Lasersköld Apr 29 '21 at 05:49
  • Thanks I understand now. I think I was overcomplicating things, when I just needed to accept the syntax for what it is rather than thinking I am missing something. – xtryingx Apr 29 '21 at 19:30
  • @Lasersköld, you're correct. Non-static data member initialization has been around since C++11. I've edited my answer to remove the inaccuracy and to point out how to get more information about it. Thank you for pointing it out. – Luis Guzman Apr 30 '21 at 03:58
1

There is a answer that states that you cannot use class member initalization that is accepted, that is false though. You just need to use braces list insteada of parenthesis. (Its another question if you actually want to use it)

Example application:

#include <string>

// Dummy code
class SAConnection {};
class SACommand {
    public:
    SACommand(SAConnection *) {}
};

// 
class DbConnection
{
    SAConnection con;
    SACommand cmd{&con}; // <-- use brace syntax, remember initialization ordering
};

int main() {
}
Lasersköld
  • 2,028
  • 14
  • 20
0
    {
    SAConnection con;
    SACommand cmd;      // this is just a declaration
    int age;
    int id;

    public: //this is the constructor
    DbConnection ():con (), cmd (&con), age (0), id (0) // here you initialize it
    {

    }
    //Some Code Here...

    };
Saj Gur
  • 5
  • 2