如何定义从虚拟函数继承的静态函数?
How to define a static function inherited from a virtual one?
我正在为一个小应用程序使用 C++。
我有一个 parent class 有一个虚方法。这是头文件。
class personDB:public person
{
public:
unsigned int id;
public:
personDB();
personDB(QString dbName, QString dbSurname);
personDB(QString dbName, QString dbSurname, unsigned int dbid);
personDB(std::string dbName, std::string dbSurname, unsigned int dbid);
virtual std::string getTableName();
unsigned int getID(void);
void setID(unsigned int myID);
private:
static const std::string tableName;
};
这个class被不同的childclass继承。每个 child class 重新定义 tableName
属性,在 *.cpp 文件中分配不同的值。该属性是私有的,由 getter 返回。
作为其中一个 child classes 的示例,这里是头文件:
#include "persondb.h"
class ScriptBy : public personDB
{
public:
ScriptBy();
ScriptBy(QString dbName, QString dbSurname);
ScriptBy(QString dbName, QString dbSurname, unsigned int dbid);
std::string getTableName();
protected:
static const std::string tableName;
};
我想使函数 getTableName() 成为 class 成员函数,以便它 returns 对于相同 class 的所有实例具有相同的值,甚至可以调用没有 class 的实例。如果我没记错的话,这应该通过在头文件中的函数声明之前放置关键字 static
来完成。但是,当我尝试以这种方式编译时,它会给我一个与 parent class 中的函数被声明为虚拟函数相关的错误。
我得到的错误是:
In file included from ../../singlestory.h:4:0,
from ../../volume.h:5,
from ../../dbinterface.h:8,
from ../../dbinterface.cpp:1:
../../scriptby.h:12:24: error: ‘static std::__cxx11::string ScriptBy::getTableName()’ cannot be declared
static std::string getTableName();
^
In file included from ../../dbinterface.h:7:0,
from ../../dbinterface.cpp:1:
../../persondb.h:15:25: error: since ‘virtual std::__cxx11::string personDB::getTableName()’ declared in base class
virtual std::string getTableName();
有没有办法让继承的class成员函数静态化?
编辑:如果我不能使函数静态化,如何在没有 class 实例的情况下使私有属性在外部可访问(并保持私有)?
"Is there a way to make the inherited class member function static?" 否
Is there a way to make the inherited class member function static?
你不能。您可以将 static
函数重命名为其他名称并从常规成员函数中使用它,如果这对您的 class.
有意义的话
class ScriptBy : public personDB
{
virtual std::string getTableName() { return getTableNameStatic(); }
static std::string getTableNameStatic();
};
virtual
和 static
代表 2 个相互矛盾的要求。
static
函数是一个 class-level 构造,不限于任何特定的 class 实例。
virtual
函数是一个 instance-level 构造,因此它的行为由相关对象定义。
您需要重新考虑您的要求。
我找到了使用 Curiously Recurring template pattern 的解决方案。
对我有用的解决方案如下:
文件persondb.h
#ifndef PERSONDB_H
#define PERSONDB_H
#include "person.h"
#include"common.h"
class personDB:public person
{
public:
using person::person;
personDB(QString dbName, QString dbSurname, unsigned int dbid);
personDB(std::string dbName, std::string dbSurname, unsigned int dbid);
unsigned int getID(void);
void setID(unsigned int myID);
protected:
unsigned int id;
};
/* Curiously recurring template paradigm */
template<class Derived>
class PersonDBX: public virtual personDB
{
using personDB::personDB;
protected:
static const std::string tableName;
static const personRelationTable personIDtable;
public:
static std::string static_getTableName(){ return tableName; }
std::string getTableName(){return tableName;}
static std::string static_getIDTableName(){ return personIDtable.tableName; }
std::string getIDTableName(){return personIDtable.tableName;}
static std::string static_getCol1TableID(){ return personIDtable.col1; }
std::string getCol1TableID(){return personIDtable.col1;}
static std::string static_getCol2TableID(){ return personIDtable.col2; }
std::string getCol2TableID(){return personIDtable.col2;}
personDBX(QString dbName, QString dbSurname, unsigned int dbid):personDB(dbName, dbSurname)
{
id = dbid;
}
PersonDBX():personDB(){;}
PersonDBX(QString dbName, QString dbSurname):personDB(dbName, dbSurname){;}
};
template<class Derived> const std::string PersonDBX<Derived>::tableName = "Null";
template<class Derived> const personRelationTable PersonDBX<Derived>::personIDtable = {"Null", "Null", "Null"};
#endif // PERSONDB_H
文件persondb.cpp
#include "persondb.h"
personDB::personDB(QString dbName, QString dbSurname, unsigned int dbid):person(dbName, dbSurname){
id = dbid;
}
personDB::personDB(std::string dbName, std::string dbSurname,
unsigned int dbid):person(dbName, dbSurname){
id = dbid;
}
unsigned int personDB::getID(void){
return id;
}
void personDB::setID(unsigned int myID)
{
id = myID;
}
child class 是 scriptby:
文件scriptby.h
#ifndef SCRIPT_H
#define SCRIPT_H
#include "persondb.h"
class ScriptBy : public PersonDBX<ScriptBy>
{
public:
using PersonDBX::PersonDBX;
ScriptBy(QString dbName, QString dbSurname, unsigned int dbid);
protected:
};
#endif // SCRIPT_H
文件scriptby.cpp
#include "scriptby.h"
#include <iostream>
#include <globals.h>
template<> const std::string PersonDBX<ScriptBy>::tableName = "ScriptBy";
template<> const personRelationTable PersonDBX<ScriptBy>::personIDtable = {"Story_ScriptBy","StoryID", "ScriptByID"};
ScriptBy::ScriptBy(QString dbName, QString dbSurname, unsigned int dbid):PersonDBX(dbName, dbSurname)
{
id = dbid;
}
我正在为一个小应用程序使用 C++。 我有一个 parent class 有一个虚方法。这是头文件。
class personDB:public person
{
public:
unsigned int id;
public:
personDB();
personDB(QString dbName, QString dbSurname);
personDB(QString dbName, QString dbSurname, unsigned int dbid);
personDB(std::string dbName, std::string dbSurname, unsigned int dbid);
virtual std::string getTableName();
unsigned int getID(void);
void setID(unsigned int myID);
private:
static const std::string tableName;
};
这个class被不同的childclass继承。每个 child class 重新定义 tableName
属性,在 *.cpp 文件中分配不同的值。该属性是私有的,由 getter 返回。
作为其中一个 child classes 的示例,这里是头文件:
#include "persondb.h"
class ScriptBy : public personDB
{
public:
ScriptBy();
ScriptBy(QString dbName, QString dbSurname);
ScriptBy(QString dbName, QString dbSurname, unsigned int dbid);
std::string getTableName();
protected:
static const std::string tableName;
};
我想使函数 getTableName() 成为 class 成员函数,以便它 returns 对于相同 class 的所有实例具有相同的值,甚至可以调用没有 class 的实例。如果我没记错的话,这应该通过在头文件中的函数声明之前放置关键字 static
来完成。但是,当我尝试以这种方式编译时,它会给我一个与 parent class 中的函数被声明为虚拟函数相关的错误。
我得到的错误是:
In file included from ../../singlestory.h:4:0,
from ../../volume.h:5,
from ../../dbinterface.h:8,
from ../../dbinterface.cpp:1:
../../scriptby.h:12:24: error: ‘static std::__cxx11::string ScriptBy::getTableName()’ cannot be declared
static std::string getTableName();
^
In file included from ../../dbinterface.h:7:0,
from ../../dbinterface.cpp:1:
../../persondb.h:15:25: error: since ‘virtual std::__cxx11::string personDB::getTableName()’ declared in base class
virtual std::string getTableName();
有没有办法让继承的class成员函数静态化?
编辑:如果我不能使函数静态化,如何在没有 class 实例的情况下使私有属性在外部可访问(并保持私有)?
"Is there a way to make the inherited class member function static?" 否
Is there a way to make the inherited class member function static?
你不能。您可以将 static
函数重命名为其他名称并从常规成员函数中使用它,如果这对您的 class.
class ScriptBy : public personDB
{
virtual std::string getTableName() { return getTableNameStatic(); }
static std::string getTableNameStatic();
};
virtual
和 static
代表 2 个相互矛盾的要求。
static
函数是一个 class-level 构造,不限于任何特定的 class 实例。
virtual
函数是一个 instance-level 构造,因此它的行为由相关对象定义。
您需要重新考虑您的要求。
我找到了使用 Curiously Recurring template pattern 的解决方案。
对我有用的解决方案如下:
文件persondb.h
#ifndef PERSONDB_H
#define PERSONDB_H
#include "person.h"
#include"common.h"
class personDB:public person
{
public:
using person::person;
personDB(QString dbName, QString dbSurname, unsigned int dbid);
personDB(std::string dbName, std::string dbSurname, unsigned int dbid);
unsigned int getID(void);
void setID(unsigned int myID);
protected:
unsigned int id;
};
/* Curiously recurring template paradigm */
template<class Derived>
class PersonDBX: public virtual personDB
{
using personDB::personDB;
protected:
static const std::string tableName;
static const personRelationTable personIDtable;
public:
static std::string static_getTableName(){ return tableName; }
std::string getTableName(){return tableName;}
static std::string static_getIDTableName(){ return personIDtable.tableName; }
std::string getIDTableName(){return personIDtable.tableName;}
static std::string static_getCol1TableID(){ return personIDtable.col1; }
std::string getCol1TableID(){return personIDtable.col1;}
static std::string static_getCol2TableID(){ return personIDtable.col2; }
std::string getCol2TableID(){return personIDtable.col2;}
personDBX(QString dbName, QString dbSurname, unsigned int dbid):personDB(dbName, dbSurname)
{
id = dbid;
}
PersonDBX():personDB(){;}
PersonDBX(QString dbName, QString dbSurname):personDB(dbName, dbSurname){;}
};
template<class Derived> const std::string PersonDBX<Derived>::tableName = "Null";
template<class Derived> const personRelationTable PersonDBX<Derived>::personIDtable = {"Null", "Null", "Null"};
#endif // PERSONDB_H
文件persondb.cpp
#include "persondb.h"
personDB::personDB(QString dbName, QString dbSurname, unsigned int dbid):person(dbName, dbSurname){
id = dbid;
}
personDB::personDB(std::string dbName, std::string dbSurname,
unsigned int dbid):person(dbName, dbSurname){
id = dbid;
}
unsigned int personDB::getID(void){
return id;
}
void personDB::setID(unsigned int myID)
{
id = myID;
}
child class 是 scriptby:
文件scriptby.h
#ifndef SCRIPT_H
#define SCRIPT_H
#include "persondb.h"
class ScriptBy : public PersonDBX<ScriptBy>
{
public:
using PersonDBX::PersonDBX;
ScriptBy(QString dbName, QString dbSurname, unsigned int dbid);
protected:
};
#endif // SCRIPT_H
文件scriptby.cpp
#include "scriptby.h"
#include <iostream>
#include <globals.h>
template<> const std::string PersonDBX<ScriptBy>::tableName = "ScriptBy";
template<> const personRelationTable PersonDBX<ScriptBy>::personIDtable = {"Story_ScriptBy","StoryID", "ScriptByID"};
ScriptBy::ScriptBy(QString dbName, QString dbSurname, unsigned int dbid):PersonDBX(dbName, dbSurname)
{
id = dbid;
}