类外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 static has several different meanings in C++, and the code you've written above uses them in two different ways.

In the context of member functions, static means "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, static means "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关键字?的更多相关文章

  1. C++:类的成员函数定义方式

    1.成员函数的第一种定义方式:在类声明中只给出成员函数的原型,而将成员函数的定义 放在类的外部. 返回值类型 类名::成员函数名(参数表) {      函数体  } class Point{ pub ...

  2. MFC 线程的创建,线程函数在类内、类外

    [线程的创建] AfxBeginThread(类外的线程函数,NULL); AfxBeginThread(类内的线程函数,(LPVOID)this); [类外线程函数] UINT 函数名(LPVOID ...

  3. Python函数定义和使用

    函数是一段可以重复多次调用的代码,通过输入的参数值,返回需要的结果.通过使用函数,可以提高代码的重复利用率.本文主要介绍Python函数的定义.调用和函数参数设置方法. 函数的定义 Python函数定 ...

  4. C++笔记——类(0)定义、访问控制、友元、default、mutable、构造函数

    整理一下一些关于类的知识点,毕竟还是很经常用的(先总结一部分,太多了). 定义格式.访问控制 C++里面定义类的关键词有两个,一个是class,另一个是struct,他们基本没有区别,除了成员变量的默 ...

  5. Java中主类中定义方法加static和不加static的区别

     Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在主方法调用(类名.方法),后者必须先实例化后用实例调用) 知识点:1.Getter and Setter 的应用 ...

  6. 关于static函数在类中的定义和使用

    刷题的时候遇到了这样一个问题:平时经常使用 sort()函数, 对结构体进行排序, 但是在类中使用时会出现 这样的错误提示:“Solution::cmp”: 函数调用缺少参数列表:请使用“&S ...

  7. Java基础(42):Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在主方法调用,后者必须先实例化后用实例调用)

    package lsg.ap.april4th2; /* 知识点:1.Getter and Setter 的应用 2.局部变量与成员变量(也可叫做全局变量) 3.Static关键字的用法 a.成员变量 ...

  8. C++类的成员函数(在类外定义成员函数、inline成员函数)

    类的成员函数(简称类函数)是函数的一种,它的用法和作用和前面介绍过的函数基本上是一样的,它也有返回值和函数类型,它与一般函数的区别只是:它是属于一个类的成员,出现在类体中.它可以被指定为private ...

  9. c++学习笔记之基础---类内声明函数后在类外定义的一种方法

    在C++的“类”中经常遇到这样的函数, 返回值类型名 类名::函数成员名(参数表){ 函数体.} 双冒号的作用 ::域名解析符!返回值类型名 类名::函数成员名(参数表) { 函数体. } 这个是在类 ...

  10. 为什么static数据成员一定要在类外初始化?(转)

    1.避免重复定义和初始化 <<c++ primer>>说在类外定义和初始化是保证static成员变量只被定义一次的好方法. 但,为什么static const int就可以在类 ...

随机推荐

  1. 推荐一款功能齐全的开源MES/万界星空科技mes

    推荐一款功能齐全的开源MES 万界星空科技商业开源MES可以提供包括制造数据管理.计划排程管理.生产调度管理.库存管理.质量管理.人力资源管理.工作中心/设备管理.工具工装管理.采购管理.成本管理.项 ...

  2. 春秋云镜 - CVE-2022-30887

    多语言药房管理系统 (MPMS) 是用 PHP 和 MySQL 开发的, 该软件的主要目的是在药房和客户之间提供一套接口,客户是该软件的主要用户.该软件有助于为药房业务创建一个综合数据库,并根据到期. ...

  3. PyTorch项目源码学习(3)——Module类初步学习

    torch.nn.Module Module类是用户使用torch来自定义网络模型的基础,Module的设计要求包括低耦合性,高模块化等等.一般来说,计算图上所有的子图都可以是Module的子类,包括 ...

  4. 占位图片(Placeholder Image)

    一.引言 在网页设计和开发中,占位图片(Placeholder Image)是一种常见的技术手段,用于在用户上传图片之前或者图片加载失败时,展示一个临时替代的图片,以提高用户体验.本文将详细介绍占位图 ...

  5. Langchain-Chatchat项目:2.1-通过GPT2模型来检索NebulaGraph

      在官方例子中给出了通过chain = NebulaGraphQAChain.from_llm(ChatOpenAI(temperature=0), graph=graph, verbose=Tru ...

  6. 浅析AIGC for MMKG

    摘要:AIGC和多模态知识图谱(MMKG)中的知识获取又是怎么实现的呢?他们之间有什么关联呢? 本文分享自华为云社区<GPT-4发布,AIGC时代的多模态还能走多远?系列之四 AIGC for ...

  7. 解读顶会ICDE’21论文:利用DAEMON算法解决多维时序异常检测问题

    摘要:该论文针对多维时序数据的异常检测问题,提出了基于GAN和AutoEncoder的深度神经网络算法,并取得了当前State of the Art (SOTA)的检测效果.论文是云数据库创新LAB在 ...

  8. 在毫秒量级上做到“更快”!DataTester 助力飞书提升页面秒开率

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 用户体验是决定互联网产品能否长久生存的基础,每一个基于产品功能.使用.外观的微小体验,都将极大关系到用户留存影响. ...

  9. Windows 2016 安装 Docker

    打开 PowerShell Windows PowerShell 版权所有 (C) 2016 Microsoft Corporation.保留所有权利. PS C:\Users\Administrat ...

  10. 聊聊损失函数1. 噪声鲁棒损失函数简析 & 代码实现

    今天来聊聊非常规的损失函数.在常用的分类交叉熵,以及回归均方误差之外,针对训练样本可能存在的数据长尾,标签噪声,数据不均衡等问题,我们来聊聊适用不同场景有针对性的损失函数.第一章我们介绍,当标注标签存 ...