类外static函数定义要不要加static关键字?
类外static函数定义要不要加static关键字?
先说答案:不需要。
错误代码:
#include<iostream>
#include<memory>
using namespace std;
class Base {
public:
enum class Type {
Derived1,
Derived2,
Derived3
};
static Base* create(Type type);
};
class Derived1 : public Base {
public:
static Base* create() {
cout<<"new 1"<<endl;
return new Derived1();
}
};
class Derived2 : public Base {
public:
static Base* create() {
cout<<"new 2"<<endl;
return new Derived2();
}
};
class Derived3 : public Base {
public:
static Base* create() {
cout<<"new 3"<<endl;
return new Derived3();
}
};
static Base* Base::create(Type type) { // 此处不应加static关键字
switch (type) {
case Type::Derived1:
return Derived1::create();
case Type::Derived2:
return Derived2::create();
case Type::Derived3:
return Derived3::create();
default:
return nullptr;
}
}
int main(){
Base* obj = Base::create(Base::Type::Derived1);
return 0;
}
编译报错:

这段代码的目的是使用工厂模式,在基类的static函数中,根据输入参数选择不同的派生类对象来返回。
在这里static成员函数是无法在类内直接定义的,这与static无关,只是因为在函数中使用到了在下方定义的派生类,编译为顺序编译,所以无法找到下面的派生类的声明,所以只能在类外定义。
报错解释:
报错意思是:
无法声明该成员函数具有静态链接。静态链接属性是指函数在编译时被链接到程序的静态存储区域,而不是在运行时动态链接到程序的堆栈中。这意味着该函数的内存地址在程序运行期间是固定的,不会随着函数的调用而改变。这与静态成员函数的目的相同,那为什么不可以如此声明呢?StackOverflow上解答如下:
The keyword
statichas several different meanings in C++, and the code you've written above uses them in two different ways.In the context of member functions,
staticmeans "this member function does not have a receiver object. It's basically a normal function that's nested inside of the scope of the class."In the context of function declarations,
staticmeans "this function is scoped only to this file and can't be called from other places."the compiler interpreted the static here to mean "I'm implementing this member function, and I want to make that function local just to this file." That's not allowed in C++ because it causes some confusion: if multiple different files all defined their own implementation of a member function and then declared them static to avoid collisions at linking, calling the same member function from different places would result in different behavior!
即如果在多个文件里定义相同的静态成员函数,它们都是仅对本文件有效的。他们会链接到不同的静态区地址。而正常的静态成员函数只有一个地址,不管哪个对象从何处调用都是调用的同一个静态成员函数,这就会导致调用时的不同行为产生,C++不允许这样做,所以报错说:我们不允许你定义一个静态链接。但我们已经声明了静态链接,编译器后续就会知道这个定义是一个静态成员函数的定义
解决方案
只需要去除定义中的static即可,在声明中标注static关键字已经足够。
类外static函数定义要不要加static关键字?的更多相关文章
- C++:类的成员函数定义方式
1.成员函数的第一种定义方式:在类声明中只给出成员函数的原型,而将成员函数的定义 放在类的外部. 返回值类型 类名::成员函数名(参数表) { 函数体 } class Point{ pub ...
- MFC 线程的创建,线程函数在类内、类外
[线程的创建] AfxBeginThread(类外的线程函数,NULL); AfxBeginThread(类内的线程函数,(LPVOID)this); [类外线程函数] UINT 函数名(LPVOID ...
- Python函数定义和使用
函数是一段可以重复多次调用的代码,通过输入的参数值,返回需要的结果.通过使用函数,可以提高代码的重复利用率.本文主要介绍Python函数的定义.调用和函数参数设置方法. 函数的定义 Python函数定 ...
- C++笔记——类(0)定义、访问控制、友元、default、mutable、构造函数
整理一下一些关于类的知识点,毕竟还是很经常用的(先总结一部分,太多了). 定义格式.访问控制 C++里面定义类的关键词有两个,一个是class,另一个是struct,他们基本没有区别,除了成员变量的默 ...
- Java中主类中定义方法加static和不加static的区别
Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在主方法调用(类名.方法),后者必须先实例化后用实例调用) 知识点:1.Getter and Setter 的应用 ...
- 关于static函数在类中的定义和使用
刷题的时候遇到了这样一个问题:平时经常使用 sort()函数, 对结构体进行排序, 但是在类中使用时会出现 这样的错误提示:“Solution::cmp”: 函数调用缺少参数列表:请使用“&S ...
- Java基础(42):Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在主方法调用,后者必须先实例化后用实例调用)
package lsg.ap.april4th2; /* 知识点:1.Getter and Setter 的应用 2.局部变量与成员变量(也可叫做全局变量) 3.Static关键字的用法 a.成员变量 ...
- C++类的成员函数(在类外定义成员函数、inline成员函数)
类的成员函数(简称类函数)是函数的一种,它的用法和作用和前面介绍过的函数基本上是一样的,它也有返回值和函数类型,它与一般函数的区别只是:它是属于一个类的成员,出现在类体中.它可以被指定为private ...
- c++学习笔记之基础---类内声明函数后在类外定义的一种方法
在C++的“类”中经常遇到这样的函数, 返回值类型名 类名::函数成员名(参数表){ 函数体.} 双冒号的作用 ::域名解析符!返回值类型名 类名::函数成员名(参数表) { 函数体. } 这个是在类 ...
- 为什么static数据成员一定要在类外初始化?(转)
1.避免重复定义和初始化 <<c++ primer>>说在类外定义和初始化是保证static成员变量只被定义一次的好方法. 但,为什么static const int就可以在类 ...
随机推荐
- 将微服务注册到nacos中
将微服务注册到nacos中将微服务注册到nacos中 首先修改pom文件,引入nacos依赖,名为spring-cloud-starter-nacos-discovery <dependency ...
- 在IDEA启动多个Spring Boot工程实例
在IDEA上点击Application右边的下三角 ,弹出选项后,点击Edit Configuration 选中需要多实例启动的应用,将默认的Single instance only(单实例)的钩去掉 ...
- 【笔记】 springCloud-configServer配置中心
当然第一步还是得要了解啦! 介绍 做项目, 那么就少不了配置微服务架构中,配置文件众多,各个服务的配置文件也有可能不一样, Spring为我们提供了相应的配置中心组件--Spring Cloud co ...
- STM32CubeMX教程3 GPIO输入 - 按键响应
1.准备材料 开发板(STM32F407G-DISC1) ST-LINK/V2驱动 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) 2 ...
- DVWA CSRF:Cross-site request forgery(跨站请求伪造)全等级
CSRF:Cross-site request forgery(跨站请求伪造) 目录: CSRF:Cross-site request forgery(跨站请求伪造) 1.Low 2.Medium 3 ...
- 在终端输入EOF
在终端输入EOF 问题 如下是一个计算校验和的程序,其中使用了while循环,需要在标准输入中读取到EOF才能跳出循环. #include <stdio.h> int main(){ in ...
- String 类和 STL (Standard Template Library)
目录 一. string 类 1. 构造字符串 2. string类输入 3. 使用字符串 4. 其他string类方法 5. 字符串种类 一. string 类 很多应用程序都需要处理字符串.C语言 ...
- bazel 使用 gtest/gmock 报错 Constraints from @bazel_tools//platforms have been removed
问题描述 运行 bazel test 命令,遇到错误:"Constraints from @bazel_tools//platforms have been removed. Please ...
- GaussDB(for MySQL)新特性TDE发布:支持透明数据加密
本文分享自华为云社区<GaussDB(for MySQL)新特性TDE发布:支持透明数据加密>,作者: GaussDB 数据库. 技术背景 为了保护数据的安全,我们可能通过防火墙.身份认证 ...
- 关于GO语言,这篇文章讲的很明白
摘要:本文从Go的语法,类型系统,编码风格,语言工具,编码工具和使用案例等几方面对Go语言进行了学习和探讨. Go语言发布之后,很多公司特别是云厂商也开始用Go语言重构产品的基础架构,而且很多企业都是 ...