类外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. 整一个工具类【根据URL地址获取file文件对象】

    整一个工具类[根据URL地址获取file文件对象] 直接将网络url文件转换为file对象 import java.io.*; import java.net.URL; public class Im ...

  2. 当创建一个ingress后,kubernetes会发什么?

    本文分享自华为云社区<当创建一个ingress后,kubernetes会发什么?>,作者:可以交个朋友. 一.Ingress概述 Ingress是一组路由转发规则合集,将集群内部服务通过7 ...

  3. libGDX游戏开发之Box2D(十四)

    libGDX游戏开发之Box2D(十四) libGDX系列,游戏开发有unity3D巴拉巴拉的,为啥还用java开发?因为我是Java程序员emm-国内用libgdx比较少,多数情况需要去官网和goo ...

  4. 一行代码解决Three.js中只能在一侧看到物体的问题

    项目场景:   因为该项目比较复杂庞大,在此就简单介绍一下:   通过Three.js创建若干个物体进行了组装,从而形成了一个类似眼球模拟模型的项目,用户可以通过拖动鼠标来达到控制视角(摄像机)的目的 ...

  5. ThreadLocal真的会造成内存泄漏吗?

    ThreadLoca在并发场景中,应用非常多.那ThreadLocal是不是真的会造成内存泄漏?今天给大家做一个分享,个人见解,仅供参考. 1.ThreadLocal的基本原理 简单介绍一下Threa ...

  6. CSS 基础 2 - Box Model 盒模型

    CSS 基础 2 - Box Model 盒模型 Box Model 盒模型是网页布局的前提.网页布局的几种方式: Table(过时):在 CSS 出现之前,一般用表格布局(将表格边框线隐藏) Flo ...

  7. SVN工具基础知识

    SVN工具基础知识 1.简介 1.全称Subversion,是一个开放源代码的版本控制系统,Subversion 在 2000 年由 CollabNet Inc 开发,现 在发展成为 Apache 软 ...

  8. 论文分享丨Holistic Evaluation of Language Models

    摘要:该文为大模型评估方向的综述论文. 本文分享自华为云社区<[论文分享]<Holistic Evaluation of Language Models>>,作者:DevAI. ...

  9. 实战案例丨分布式系统中如何用python实现Paxos

    摘要:提到分布式算法,就不得不提 Paxos 算法,在过去几十年里,它基本上是分布式共识的代 名词,因为当前最常用的一批共识算法都是基于它改进的.比如,Fast Paxos 算法. Cheap Pax ...

  10. HBuilderX获取iOS证书的打包步骤

    简介: 目前app开发,很多企业都用H5框架来开发,而uniapp又是这些h5框架里面最成熟的,因此hbuilderx就成为了开发者的首选.然而,打包APP是需要证书的,那么这个证书又是如何获得呢? ...