Inconsistent method declarations in duplicated types - c++-cli

I'm making a class in c++-cli, and I added an extra argument to one of my functions. The name of the extra argument was int row,and when I add that I get this error:
LNK2022 metadata operation failed (80131187) : Inconsistent method declarations in duplicated types (types: query; methods: Read_DB)
When I remove that extra argument I added, the error goes away. If I remove the argument column_index, it also goes away. But if I remove one of the String^ arguments, it still stays. I'm not sure what the error is, here's both my .h and the functions definition in the .cpp file of code:
Header:
#ifndef DATA_BASE
#define DATA_BASE
using namespace System;
using namespace System::Data::SqlClient;
ref class ConnectDB{
protected:
SqlConnection^ cnn;
bool state;
public:
String^ db;
bool ConnectDataBase();
bool DisconnectDataBase(void);
};
ref class Query : public ConnectDB {
private:
~Query(void);
public:
bool Create_Table(String^ name, String^ columns);
String^ Read_DB(String^ column, String^ table, int column_index, int row);
bool Write_DB(String^ path, String^ msg);
};
#endif
cpp file:
String^ Query::Read_DB(String^ column, String^ table, int column_index, int row) {
String^ output;
String^ sql = "SELECT " + column + " FROM " + table;
try {
SqlCommand^ command;
SqlDataReader^ dataReader;
command = gcnew SqlCommand(sql, cnn);
dataReader = command->ExecuteReader();
std::cout << "Reading data from Database...\n";
int counter;
while (dataReader->Read()) {
counter++;
if(counter == row)
output = (String^)dataReader->GetValue(column_index);
}
//command->Dispose();
dataReader->Close();
}
catch (Exception^ e) {
Console::WriteLine(e);
std::cout << "Failed to query database\n";
return "0";
}
return output;
}

to fix the problem I just deleted the debug folder and restarted my application. It had something to do with changing the name of the object.

Related

Function not working when inside if or switch statements

I need to solve a OOP problem in which I have to manage multiple classes inherited by each other. First I need to read all the data for all the Employees of a Company. The reading runs very well but I also need to display the read data after reading the command 1 (I need to use switch). I created a function "afisare_angajati()" which only works outside "if" and "switch" statements. I don't know why those statements disable my function. This happened to me before but I couldn't find the cause. Is something that I am not seeing? You can see my function at the end of the code. Thx for help.
#include<iostream>
#include<string>
#include<vector>
class Angajat{
protected:
std::string nume;
float salariu_baza;
std::string functie;
float procent_taxe_salariu;
public:
float get_salariu_net(){return 0;}
float get_salariu_brut(){return 0;}
std::string get_nume(){return 0;}
void marire_salariu(){}
Angajat(std::string nume,float salariu_baza,std::string functie,float procent_taxe_salariu=40):
nume(nume),salariu_baza(salariu_baza),functie(functie),procent_taxe_salariu(procent_taxe_salariu){}
void display(){
std::cout<<nume<<'\n';
std::cout<<functie<<'\n';
}
};
class Analist:public Angajat{
public:
Analist(std::string nume,float salariu_baza,std::string functie,float procent_taxe_salariu=40):
Angajat(nume,salariu_baza,functie,procent_taxe_salariu){}
};
class Programator:public Analist{
protected:
float procent_deducere_salariu_it;
public:
Programator(std::string nume,float salariu_baza,std::string functie,float procent_taxe_salariu=40):
Analist(nume,salariu_baza,functie,procent_taxe_salariu){}
};
class LiderEchipaProgramare:public Programator{
protected:
int vechime;
float bonus_vechime;
public:
LiderEchipaProgramare(std::string nume,float salariu_baza,std::string functie,int vechime,float procent_taxe_salariu=40):
Programator(nume,salariu_baza,functie,procent_taxe_salariu),vechime(vechime){
bonus_vechime=500;
}
};
class FirmaProgramare{
private:
std::vector<Angajat*> vec_ang;
public:
void afisare_angajati(){
for(Angajat* a:vec_ang){
a->display();
}
}
void mareste_salarii(float,float,float){}
void promoveaza(std::string){}
void adauga_angajat(Angajat* a){
vec_ang.push_back(a);
}
};
int main(){
std::string nume;
std::string functie;
float salariu_baza;
int vechime;
int nr_ang,comanda;
FirmaProgramare pula;
std::cin>>nr_ang;
for(int i=0;i<nr_ang;++i){
std::cin.ignore();
std::getline(std::cin,nume);
std::cin>>functie;
std::cin>>salariu_baza;
Angajat* p = nullptr;
if(functie=="Analist"){
p = new Analist(nume,salariu_baza,functie);
}
else{
if(functie=="Programator"){
p = new Programator(nume,salariu_baza,functie);
}
else{
p = new LiderEchipaProgramare(nume,salariu_baza,functie,vechime);
}
}
pula.adauga_angajat(p);
}
std::cin>>comanda;
//pula.afisare_angajati(); output is correct if I put the function outside of brackets
switch(comanda)
{
case 1:{
pula.afisare_angajati();
break;
}
}
}

Initialize C++/CLI array of structures

I wish to partially initialize an array of structures like in a C++ POD type. The String^ would normally be a char* but managed C++ doesn't allow that.
#include "stdafx.h"
using namespace System;
ref struct Field
{
String^ name;
int fences;
int length;
};
int main(array<System::String ^> ^args)
{
array<Field^>^ farm =
{
{ "eenie", 10 },
{ "meenie", 20 },
{ "miny", 4 }
};
for each (Field^ field in farm)
{
field->length = field->fences * 22;
}
return 0;
}
This results in
1>arrayinit.cpp(18): error C2440: 'initializing' : cannot convert from 'const char [6]' to 'Field ^'
1> Reason: cannot convert from 'const char *' to 'Field ^'
1> No user-defined-conversion operator available, or
1> Cannot convert an unmanaged type to a managed type
So I tried
#include "stdafx.h"
using namespace System;
ref struct Field
{
String^ name;
int fences;
int length;
};
int main(array<System::String ^> ^args)
{
array<Field^>^ farm =
{
{ String("eenie"), 10 },
{ String("meenie"), 20 },
{ String("miny"), 4 }
};
for each (Field^ field in farm)
{
field->length = field->fences * 22;
}
return 0;
}
Now I get
1>arrayinit.cpp(18): error C2440: 'initializing' : cannot convert from 'System::String' to 'Field ^'
1> No user-defined-conversion operator available, or
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>arrayinit.cpp(18): error C2078: too many initializers
Almost every example I've looked at only tells how to initialize an array of strings or integers. I haven't found out a way of initializing an array of structures containing strings.
Is there a simple way of doing this or do I have to create a special constructor and gcnew every element?
I found that I can gcnew every element with a special constructor. Is there a simpler way of doing this similar to a POD initialization?
#include "stdafx.h"
using namespace System;
ref struct Field
{
String^ name;
int fences;
int length;
Field(String^ x, int in_fences)
{
name = x;
fences = in_fences;
}
};
int main(array<System::String ^> ^args)
{
array<Field^>^ farm =
{
gcnew Field("eenie", 10 ),
gcnew Field("meenie", 20 ),
gcnew Field("miny", 4 )
};
for each (Field^ field in farm)
{
field->length = field->fences * 22;
}
return 0;
}
Alternatively, if Field is changed to a value instead of a reference,
#include "stdafx.h"
using namespace System;
value struct Field
{
String^ name;
int fences;
int length;
Field(String^ x, int in_fences)
{
name = x;
fences = in_fences;
}
void Init()
{
length = fences * 22;
}
};
int main(array<System::String ^> ^args)
{
array<Field>^ farm =
{
Field("eenie", 10 ),
Field("meenie", 20 ),
Field("miny", 4 )
};
for each (Field% field in farm)
{
field.Init();
}
return 0;
}
This is slightly better than gcnewing every field.

C++/CLI error: 'a value type of "int" cannot be used to initialize an entity of type "Department ^"'

My problem is that on the line just above "return temp;" in my CreateNewDepartment function I get a weird compile error (red underline in Visual Studio). When I mouse over the compile error text ("deptId,") in "Department^ temp(deptId, var[0], var[1]);" the pop-up tip says:
a value type of "int" cannot be used to initialize an entity of type "Department ^"
Here is my code to create a new object:
Department^ CreateNewDepartment(SQLRETURN retCode, SQLHANDLE hStmt)
{
int deptId;
String^ Name;
String^ Location;
System::String^ bufN;
char buf[256];
SQLINTEGER numBytes;
for (int i = 1; i <= 3; i++)
{
retCode = SQLGetData(
hStmt,
i, // COLUMN NUMBER of the data to get
SQL_C_CHAR, // DATA TYPE that you expect to receive
buf, // BUFFER to put the data that you expect to receive
255, // BUFFER size in bytes (-1 for null terminator)
&numBytes // SIZE in bytes of data returned
);
if (CHECK(retCode, "SqlGetData", false))
{
bufN = gcnew String((char *)buf);
if (i == 1)
{
std::string s = msclr::interop::marshal_as<std::string>(bufN);
deptId = std::stoi(s, nullptr, 0);
}
else if (i == 2)
{
Name = bufN;
}
else if (i == 3)
{
Location = bufN;
}
}
}
Department^ temp(deptId, Name, Location);
return temp;
}
Department is defined thus:
ref class Department
{
private:
int _deptId;
String^ _deptName;
String^ _deptLocation;
public:
Department(int id, String^ deptName, String^ deptLocation);
<...snip...>
}
And the cstr and set functions:
Department::Department(int id, String^ deptName, String^ deptLocation)
{
setDeptId(id);
setDeptName(deptName);
setDeptLocation(deptLocation);
}
void Department::setDeptId(int id)
{
_deptId = id;
}
void Department::setDeptName(String^ name)
{
_deptName = name;
}
void Department::setDeptLocation(String^ location)
{
_deptLocation = location;
}
Sorry if this is a simple error or dumb question, but I'm new to CLI.
Department^ temp(deptId, Name, Location);
Apparently should have been:
Department^ temp(gcnew Department(deptId, Name, Location));
Although I have no idea why. lol

System::String^ to TCHAR*

I have a class which collects all paths to .txt files of a given folder and stores them into a vector. Most of the functions I use require the usage of TCHAR* to get/set current directory and so on.
The class looks like this:
typedef std::basic_string<TCHAR> tstring;
class folderManager
{
private:
TCHAR searchTemplate[MAX_PATH];
TCHAR directory[MAX_PATH];
WIN32_FIND_DATA ffd;
HANDLE hFind;
vector<tstring> folderCatalog;
vector<tstring> fileNames;
bool succeeded;
public:
// get/set methods and so on...
};
// Changed TCHAR* dir to tstring dir
void folderManager::setDirectory(tstring dir)
{
HANDLE hFind = NULL;
succeeded = false;
folderCatalog.clear();
fileNames.clear();
// Added .c_str()
SetCurrentDirectory(dir.c_str());
GetCurrentDirectoryW(MAX_PATH, directory);
TCHAR fullName[MAX_PATH];
StringCchCat(directory, MAX_PATH, L"\\");
StringCchCopy(searchTemplate, MAX_PATH, directory);
StringCchCat(searchTemplate, MAX_PATH, L"*.txt");
hFind = FindFirstFile(searchTemplate, &ffd);
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
FindClose(hFind);
return;
}
do
{
StringCchCopy(fullName, MAX_PATH, directory);
StringCchCat(fullName, MAX_PATH, ffd.cFileName);
folderCatalog.push_back(fullName);
fileNames.push_back(ffd.cFileName);
}
while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
succeeded = true;
}
This is where I need to do the conversion of System::String^ to TCHAR*
private: System::Void dienuFolderisToolStripMenuItem_Click(System::Object^
sender, System::EventArgs^ e)
{
FolderBrowserDialog^ dialog;
dialog = gcnew System::Windows::Forms::FolderBrowserDialog;
System::Windows::Forms::DialogResult result = dialog->ShowDialog();
if (result == System::Windows::Forms::DialogResult::OK)
{
// Conversion is now working.
tstring path = marshal_as<tstring>(dialog->SelectedPath);
folder->setDirectory(path);
}
}
marsha_as "Performs the marshaling on a specific data object to convert it between a managed and a native data type".
Here there is the table for possible type conversion.
I use it this way:
marshal_as<std::wstring>(value)
TCHAR can be char or wchar_t, both of them present in marshal_as specialization, I suppose you need to point TCHAR* as template parameter:
TCHAR* result = marshal_as<TCHAR*>(value)
Actually MSDN says that you have to use it this way:
#include <msclr\marshal.h>
using namespace System;
using namespace msclr::interop;
int main(array<System::String ^> ^args)
{
System::String^ managedString = gcnew System::String("Hello World!!!");
marshal_context ^ context = gcnew marshal_context();
const wchar_t* nativeString = context->marshal_as<const wchar_t*>(managedString);
//use nativeString
delete context;
return 0;
}

Multiple dispatch and multi-methods

What are they, what's the different between them?
Many sources, like Wikipedia, claim they're the same thing, but others explicitly say the opposite, like sbi in this question:
First: "Visitor Pattern is a way to simulate Double Dispatching in C++." This is, erm, not fully right. Actually, double dispatch is one form of multiple dispatch, which is a way to simulate (the missing) multi-methods in C++.
They are the same.
When you call a virtual method in C++, the actual method to run is based on the runtime type of the object them method is invoked on. This is called "single dispatch" because it depends on the type of a single argument (in this case, the implicit 'this' argument). So, for example, the following:
class Base {
public:
virtual int Foo() { return 3; }
}
class Derived : public Base {
public:
virtual int Foo() { return 123; }
}
int main(int argc, char *argv[]) {
Base* base = new Derived;
cout << "The result is " << base->Foo();
delete base;
return 0;
}
When run, the above program prints 123, not 3. So far so good.
Multiple-dispatch is the ability of a language or runtime to dispatch on both the type of the 'this' pointer and the type of the arguments to the method. Consider (sticking with C++ syntax for the moment):
class Derived;
class Base {
public:
virtual int Foo(Base *b) { cout << "Called Base::Foo with a Base*"; }
virtual int Foo(Derived *d) { cout << "Called Base::Foo with a Derived*"; }
}
class Derived : public Base {
public:
virtual int Foo(Base *b) { cout << "Called Derived::Foo with a Base*"; }
virtual int Foo(Derived *d) { cout << "Called Derived::Foo with a Derived*"; }
}
int main(int argc, char *argv[]) {
Base* base = new Derived;
Base* arg = new Derived;
base->Foo(arg);
delete base;
delete arg;
return 0;
}
If C++ had multiple-dispatch, the program would print out "Called Derived::Foo with a Dervied*". (Sadly, C++ does not have multiple-dispatch, and so the program prints out "Called Derived::Foo with a Base*".)
Double-dispatch is a special case of multiple-dispatch, often easier to emulate, but not terribly common as a language feature. Most languages do either single-dispatch or multiple-dispatch.