2

I'm new to C++ and this is my first time with its classes and I was wondering, how do I call a constructor? I've read some documentation on classes in C++ and that's how I came up with what I have. The constructor calls private methods to setup the server.

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sstream>
#include <string>
#include "SimpleIni.h"
#include "MySQL.cpp"
#include <thread>

class LoginServer {
    int resSocket;
    MySQL mysql;
    struct sockaddr_in strctAddr;

    private:
        void log(std::string strText, std::string strType = "INFO"){
            time_t rawtime;
            struct tm * timeinfo;
            char buffer[50];
            time(&rawtime);
            timeinfo = localtime(&rawtime);
            strftime(buffer, 50, "%c",timeinfo);
            std::cout << "[" << buffer << "][" << strType << "] > " << strText << std::endl;
        } 

        void error(std::string strError){
            log(strError, "ERROR");
            exit(1);
        }

        int setup(int intPort){
            std::stringstream objStringStream;
            objStringStream << intPort;
            log("Initializing socket server");
            resSocket = socket(AF_INET, SOCK_STREAM, 0);
            if(resSocket < 0) error("Could not create socket.");
            bzero((char *) &strctAddr, sizeof(strctAddr));
            strctAddr.sin_family = AF_INET;
            strctAddr.sin_addr.s_addr = INADDR_ANY;
            strctAddr.sin_port = htons(intPort);
            setsockopt(resSocket, SOL_SOCKET, SO_REUSEADDR, (struct sockaddr *) &strctAddr, sizeof(strctAddr));
            if(bind(resSocket, (struct sockaddr *) &strctAddr, sizeof(strctAddr)) < 0)
                error("Could not bind");
            listen(resSocket, 5);
            log("Listening for clients on " + objStringStream.str(), "FINE");
            return 1;
        }

        int sendPacket(int resSock, std::string strData){
            int intWrite;
            char chBuffer[8192];
            strcpy(chBuffer, strData.c_str());
            log("Sending packet: " + strData, "SEND");
            intWrite = write(resSock, chBuffer, strlen(chBuffer) + 1);
            return intWrite;
        }

        std::string RandomString(int len){
           srand(time(0));
           std::string str = "`~!@#$%^&*()-=_+[]\{]|;:'\",<.>/?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
           int pos;
           int size = str.size();
           while(size != len) {
            pos = ((rand() % (str.size() - 1)));
            str.erase (pos, 1);
           }
           return str;
        }

        void handleData(int resSock, char* strData){
            char * chData;
            chData = strtok(strData, "\0");
            while(chData != NULL){
                std::string strPacket = chData;
                log("Received data: " + std::string(strPacket), "RECV");
                if(strPacket.compare("<policy-file-request/>") == 0){
                    log("Policy request received");
                    sendPacket(resSock, "<cross-domain-policy><allow-access-from domain='*' to-ports='6112'/></cross-domain-policy>");
                } else if(strPacket.compare("<msg t='sys'><body action='verChk' r='0'><ver v='153' /></body></msg>") == 0){
                    log("Version check received");
                    sendPacket(resSock, "<msg t='sys'><body action='apiOK' r='0'></body></msg>");
                }
                chData = strtok(NULL, "\0");
            }
        }

        void handleClient(int resSock){
            char chBuffer[6486];
            int intRead;
            for(;;){
                bzero(chBuffer, 6486);
                intRead = read(resSock, chBuffer, 6486);
                if(chBuffer == NULL) continue;
                if(intRead <= 0){
                    log("Client disconnected");
                    close(resSock);
                    break;
                } else {
                    handleData(resSock, chBuffer);
                }
            }
        }

        void listenToClients(){
            for(;;){
                std::stringstream objStringStream;
                struct sockaddr_in clntAddr;
                socklen_t intClients = sizeof(clntAddr);
                int resClient = accept(resSocket, (struct sockaddr *) &clntAddr, &intClients);
                if(resClient < 0) log("Failed to accept client", "ERROR");
                setsockopt(resClient, SOL_SOCKET, SO_REUSEADDR, (struct sockaddr *) &clntAddr, sizeof(clntAddr));
                char floatIP[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &clntAddr.sin_addr, floatIP, sizeof floatIP);
                objStringStream << floatIP;
                log("New client connected (IP: " + objStringStream.str() + ")");
                std::thread objThread(&LoginServer::handleClient, this, resClient);
                objThread.detach();
            }
        }

    public:
        LoginServer();
};
LoginServer::LoginServer(){
    CSimpleIniA objIniParser;
    objIniParser.LoadFile("Settings.conf");
    #define Host objIniParser.GetValue("Database", "Host", NULL)
    #define User objIniParser.GetValue("Database", "User", NULL)
    #define Pass objIniParser.GetValue("Database", "Pass", NULL)
    #define Name objIniParser.GetValue("Database", "Name", NULL)    
    if(!mysql.connect(Host, User, Pass, Name)) error("Could not establish database connection.");
    setup(6112);
    listenToClients();
}

int main(){
    LoginServer objLoginServer();
    return 0;
}
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
Jenny
  • 21
  • 1
  • 3

5 Answers5

8

Due to the rules of parsing in C++:

LoginServer objLoginServer();

doesn't declare an object of type LoginServer. In fact is declares a function that takes no parameters and returns a LoginServer object by value.

Instead you want to say:

LoginServer objLoginServer;
Martin York
  • 257,169
  • 86
  • 333
  • 562
Mark B
  • 95,107
  • 10
  • 109
  • 188
4

Try removing the parentheses:

LoginServer objLoginServer;

If you are curious of what's going on, search for the "most vexing parse".

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

The constructor should be called everytime you instantiate an object, such as the line LoginServer objLoginServer; (hint: try w/o the parenthesis) or LoginServer *objLoginServer = new LoginServer();, of course remember to call delete objLoginServer; when done with it.

MartyE
  • 636
  • 3
  • 7
  • 1
    @jenny also, consider the rule of three: if you explicitly create the constructor, also explicitly create the destructor and copy constructor. – MartyE Aug 15 '12 at 04:11
0

http://www.cplusplus.com/doc/tutorial/classes/

Reading this is good start. Best of luck.

Important: Notice how if we declare a new object and we want to use its default constructor (the one without parameters), we do not include parentheses ():

CRectangle rectb;   // right
CRectangle rectb(); // wrong! 
Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
Ben
  • 669
  • 8
  • 14
  • A [good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) is a better recommendation. That site has [problems](http://jcatki.no-ip.org/fncpp/cplusplus.com), which might be the reason for the downvote. – chris Aug 15 '12 at 03:55
  • I find the site's content very well written, and I must say I do not fathom the downvotes. The answer is correct and the content of the linked page is relevant. So I believe there are some people that just fancies hitting the downvote button at random (or as a sport). -Or perhaps they bother about a detail like a spelling mistake somewhere on the linked page and yell "all of it is incorrect". –  Apr 14 '14 at 21:02
0

There are multiple ways of calling the constructor, but I guess your specific problem is that your put brackets when calling default constructor, you need to omit them: LoginServer objLoginServer;

Such problem happens because compiler isn't able to distingush between declaring function prototype and calling default constructor. Look at A B(), out of context it may be creating object with name B of type A using default constructor, or function B returning an instance of type A.

Alexander Putilin
  • 2,262
  • 2
  • 19
  • 32